package com.kakarote.examine.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import com.kakarote.core.common.cache.CrmCacheKey;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.entity.AdminUserQueryBO;
import com.kakarote.core.entity.BasePage;
import com.kakarote.core.entity.QueryParentDeptBO;
import com.kakarote.core.entity.UserInfo;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.AdminMessageBO;
import com.kakarote.core.feign.admin.entity.AdminMessageEnum;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.feign.admin.service.AdminMessageService;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.feign.examine.entity.*;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.core.utils.BaseUtil;
import com.kakarote.core.utils.UserCacheUtil;
import com.kakarote.core.utils.UserUtil;
import com.kakarote.examine.constant.*;
import com.kakarote.examine.entity.BO.*;
import com.kakarote.examine.entity.PO.ExamineRecordLog;
import com.kakarote.examine.entity.PO.*;
import com.kakarote.examine.entity.VO.*;
import com.kakarote.examine.mapper.ExamineRecordMapper;
import com.kakarote.examine.service.*;
import com.kakarote.hrm.feign.entity.HrmSalaryMonthRecord;
import com.kakarote.hrm.feign.service.SalaryRecordService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 审核记录表 服务实现类
 * </p>
 *
 * @author zhangzhiwei
 * @since 2020-11-19
 */
@Slf4j
@Service
public class ExamineRecordServiceImpl extends BaseServiceImpl<ExamineRecordMapper, ExamineRecord> implements IExamineRecordService {

    @Autowired
    private IExamineService examineService;
    @Autowired
    private IExamineFlowService examineFlowService;
    @Autowired
    private IExamineRecordLogService examineRecordLogService;

    @Autowired
    private IExamineRecordHistoryLogService examineRecordHistoryLogService;

    @Autowired
    private IExamineManagerUserService examineManagerUserService;

    @Autowired
    private IExamineRecordOptionalService recordOptionalService;

    @Autowired
    private IExamineFlowFinalService examineFlowFinalService;

    @Autowired
    private IExamineFlowFinalOptionalService examineFlowFinalOptionalService;

    @Autowired
    private IExamineAdvancedConfigService examineAdvancedConfigService;

    @Autowired
    private IExamineAdvancedConfigLimitTimeService examineAdvancedConfigLimitTimeService;

    @Autowired
    private IExamineAdvancedConfigLimitTimeUsersService advancedConfigLimitTimeUsersService;

    @Autowired
    private IExamineRecordLimitService examineRecordLimitService;

    @Autowired
    private AdminService adminService;

    @Autowired
    private SalaryRecordService salaryRecordService;

    @Autowired
    private ISuperExamineEmailService superExamineEmailService;

    @Autowired
    private IExamineDelegateService examineDelegateService;

    @Autowired
    private IExamineConditionService examineConditionService;

    @Autowired
    private IExamineFlowAuthFieldService examineFlowAuthFieldService;

    @Autowired
    private IExamineFlowFieldUpdateLogService examineFlowFieldUpdateLogService;

    @Resource IExamineFlowBindLabelService  examineFlowBindLabelService;

    private static final int ONE = 1;

    private static final int TWO = 2;

    private static final int THREE = 3;

    private static final int TWENTY = 20;


    /**
     * 审批 pro max ultra
     * 添加审批记录
     *
     * @param examineRecordSaveBO data
     */
    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 60000)
    public ExamineRecordReturnVO addExamineRecord(ExamineRecordSaveBO examineRecordSaveBO) {
        Examine examine;
        if (examineRecordSaveBO.getCategoryId() == null) {
            examine = examineService.queryExamineByLabel(examineRecordSaveBO.getLabel());
        } else {
            examine = examineService.getById(examineRecordSaveBO.getCategoryId());
        }
        // 没有可以审批流程时直接审核通过
        if (examine == null) {
            return new ExamineRecordReturnVO(null, ExamineStatusEnum.IGNORE.getStatus(), null);
        }

        ExamineAdvancedConfigVO examineAdvancedConfig = examineAdvancedConfigService.queryAdvancedConfig(examine.getBatchId());
        List<Integer> modifyPermissionType = examineAdvancedConfig.getModifyPermissionType();
        //判断是否同时包含有1，2
        boolean contains = !modifyPermissionType.contains(ONE);
        boolean contains1 = !modifyPermissionType.contains(TWO);

        if (ObjectUtil.isNotEmpty(examineAdvancedConfig)) {
            if (ObjectUtil.isNotNull(examineRecordSaveBO.getFlowDataList()) &&
                    (contains || contains1)) {
                ExamineSaveBO examineSaveBO = new ExamineSaveBO();
                examineSaveBO.setExamineId(examine.getExamineId());
                examineSaveBO.setDataList(examineRecordSaveBO.getFlowDataList());
                examine = examineService.addCustomizationExamine(examineSaveBO, examine);
            }
        }
        //编辑审批
        Long recordId = examineRecordSaveBO.getRecordId();
        boolean isInit = true;
        if (recordId != null) {
            // 默认返回初始层级
            recordOptionalService.lambdaUpdate().eq(ExamineRecordOptional::getRecordId, recordId).remove();
            examineRecordLogService.lambdaUpdate().eq(ExamineRecordLog::getRecordId, recordId).remove();
            //09  清除 现时处理逻辑
            examineRecordLimitService.removeRecordLimit(recordId);
            this.lambdaUpdate().eq(ExamineRecord::getRecordId, recordId).remove();

            //重新发起审批删除之前的 审批流程字段修改日志
            examineFlowFieldUpdateLogService.lambdaUpdate().eq(ExamineFlowFieldUpdateLog::getTypeId, examineRecordSaveBO.getTypeId())
                    .remove();
            isInit = false;

        }

        //获取第一层审批流程
        ExamineFlow examineFlow = examineFlowService.lambdaQuery()
                .eq(ExamineFlow::getExamineId, examine.getExamineId())
                .orderByAsc(ExamineFlow::getSort)
                .last("limit 1").one();

        // 没有可以审批流程时直接审核通过
        if (ObjectUtil.isEmpty(examineFlow)) {
            return new ExamineRecordReturnVO(null, ExamineStatusEnum.IGNORE.getStatus());
        }

        //获取审批流程类型
        ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

        UserInfo userInfo = UserUtil.getUser();
        // 保存审批记录
        ExamineRecord examineRecord = new ExamineRecord();
        examineRecord.setCreateUserId(userInfo.getUserId());
        examineRecord.setUpdateUserId(userInfo.getUserId());
        examineRecord.setCreateTime(LocalDateTimeUtil.now());
        examineRecord.setUpdateTime(LocalDateTimeUtil.now());
        examineRecord.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
        examineRecord.setExamineId(examine.getExamineId());
        examineRecord.setFlowId(examineFlow.getFlowId());
        examineRecord.setLabel(examineRecordSaveBO.getLabel());
        examineRecord.setTypeId(examineRecordSaveBO.getTypeId());
        examineRecord.setParentFlowId(examineRecordSaveBO.getParentFlowId());
        examineRecord.setParentRecordId(examineRecordSaveBO.getParentRecordId());
        examineRecord.setExamineReason(examineRecordSaveBO.getExamineReason());
        save(examineRecord);

        // 将新创建的记录放入缓存，设置60秒过期
        String cacheKey = CrmCacheKey.EXAMINE_RECORD_TEMP_CACHE_KEY + examineRecord.getRecordId();
        BaseUtil.getRedis().setex(cacheKey, 60, JSON.toJSONString(examineRecord));

        //获取执行的审批流程-针对条件节点
        examineFlow = examineTypeService.getAvailableFlow(examineFlow, examineRecord, examineRecordSaveBO.getDataMap());

        //获取审批流程类型
        examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

        // 保持创建人log
        ExamineRecordLog createRecordLog = new ExamineRecordLog();
        createRecordLog.setFlowId(examineFlow.getFlowId());
        createRecordLog.setCreateTime(examineRecord.getCreateTime());
        createRecordLog.setCreateUserId(userInfo.getUserId());
        createRecordLog.setExamineId(examine.getExamineId());
        createRecordLog.setExamineStatus(ExamineStatusEnum.CREATE.getStatus());
        createRecordLog.setRecordId(examineRecord.getRecordId());
        createRecordLog.setSort(0);
        createRecordLog.setBatchId(IdUtil.simpleUUID());
        createRecordLog.setExamineReason(examineRecordSaveBO.getExamineReason());
        examineRecordLogService.save(createRecordLog);

        //处理审批流程
        JSONObject results = examineTypeService.disposeFlow(examineFlow, examineRecord.getRecordId(), examineRecordSaveBO.getDataMap(), examine, isInit);

        //处理委托
        examineDelegateService.disposeDelegate(examineFlow.getFlowId(), examineRecord.getRecordId(), examineRecord.getLabel());

        Integer status = examineTypeService.handleRecordLogByAdvancedConfig(examineRecord.getRecordId(), examineFlow.getFlowId(), isInit, examineRecordSaveBO.getDataMap());

        results.putOpt("status", status);

        // 发送通知
        List<ExamineRecordLog> recordLogs = examineRecordLogService.lambdaQuery()
                .eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                .eq(ExamineRecordLog::getFlowId, examineFlow.getFlowId())
                .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                .list();

        for (ExamineRecordLog recordLog : recordLogs) {
            if (ObjectUtil.isNotEmpty(recordLog.getExamineUserEmail())) {
            } else {
                this.addMessage(examine, 1, examineRecordSaveBO.getTitle(), examineRecordSaveBO.getTypeId(), recordLog, UserUtil.getUserId(), false, examineRecordSaveBO.getExamineReason(), examineRecordSaveBO.getIsSendMessage());
            }
        }

        return new ExamineRecordReturnVO(examineRecord.getRecordId(), results.getInt("status"));
    }


    /**
     * @return
     * @Description 通过添加日志
     * @Author UNIQUE
     * @Date 2022/9/28
     * @Param
     **/
    @Override
    public List<ExamineRecordLog> addExamineRecordLogList(Integer type, Long examineId, Integer examineStatus, Long flowId, Long recordId, Integer sortId, String msgContent, String examineName, Long recordTypeId, Integer passFlag, List<ExamineFlowFinalUser> userList) {
        UserInfo userInfo = UserUtil.getUser();
        String batchId = IdUtil.simpleUUID();
        int itemsort = sortId;
        List<ExamineRecordLog> recordLogList = new ArrayList<>();
        ExamineRecord examineRecord = getById(recordId);
        LocalDateTime now = LocalDateTimeUtil.now();
        for (ExamineFlowFinalUser examineFlowFinalUser : userList) {
            ExamineRecordLog examineRecordLog = new ExamineRecordLog();
            examineRecordLog.setType(type);
            examineRecordLog.setCreateTime(now);
            examineRecordLog.setExamineTime(now);
            examineRecordLog.setUpdateTime(null);
            examineRecordLog.setCreateUserId(userInfo.getUserId());
            examineRecordLog.setExamineId(examineId);
            examineRecordLog.setExamineRoleId(0L);
            //   在这块判断审核人状态，是否有效等
            examineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
            examineRecordLog.setExamineUserEmail(examineFlowFinalUser.getEmail());
            examineRecordLog.setExamineStatus(examineStatus);
            examineRecordLog.setFlowId(flowId);
            examineRecordLog.setRecordId(recordId);
            examineRecordLog.setSort(itemsort++);
            examineRecordLog.setBatchId(batchId);
            examineRecordLog.setRemarks(msgContent);
            examineRecordLog.setPassFlag(passFlag);
            examineRecordLogService.save(examineRecordLog);
            recordLogList.add(examineRecordLog);
            if (ExamineStatusEnum.COPY.getStatus().equals(examineStatus)) {
                //发送邮件 和消息
                if (ObjectUtil.isNotEmpty(examineFlowFinalUser.getUserId())) {
                    AdminMessageBO adminMessageBO = new AdminMessageBO();
                    adminMessageBO.setUserId(examineRecord.getCreateUserId());
                    examineFlowFinalService.setCopyMessageType(adminMessageBO, examineRecord.getLabel());
                    adminMessageBO.setContent(msgContent);
                    adminMessageBO.setTitle(examineName);
                    adminMessageBO.setTypeId(recordTypeId);
                    adminMessageBO.setIds(Collections.singletonList(examineFlowFinalUser.getUserId()));
                    AdminMessageService messageService = ApplicationContextHolder.getBean(AdminMessageService.class);
                    messageService.sendMessage(adminMessageBO);
                } else {
                    if (StringUtils.isNotEmpty(examineFlowFinalUser.getEmail())) {
                    }
                }
            } else {
                if (StringUtils.isNotEmpty(examineFlowFinalUser.getEmail())) {
                }
            }
        }
        return recordLogList;
    }

    /**
     * 进行审批，此方法采用异步同步的方式同步到其他模块
     * 开启分布式事务
     * 0待审核、1通过、2拒绝、3审核中 4:撤回 5 未提交 6 创建 7 已删除 8 作废 14归档
     *
     * @param examineBO data
     */
    @Override
    @GlobalTransactional(name = "auditExamine", rollbackFor = Exception.class)
    public void auditExamine(ExamineBO examineBO) {
        UserInfo userInfo = UserUtil.getUser();
        LocalDateTime now = LocalDateTimeUtil.now();
        if (!(ObjectUtil.isNotEmpty(examineBO.getPassFlag()) && examineBO.getPassFlag().equals(1))) {
            //添加使用传入userId来进行后续审核
            examineBO.setExamineUserId(userInfo.getUserId());
        }
        ExamineRecord examineRecord = getById(examineBO.getRecordId());
        if (ObjectUtil.isEmpty(examineRecord)) {
            return;
        }
        //添加校验审批意见
        if (Objects.equals(ExamineStatusEnum.REJECT.getStatus(), examineBO.getStatus()) && ObjectUtil.isEmpty(examineBO.getRemarks())) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_PASS_OR_CANCEL_REMART_NOT_EMPTY_ERROR);
        }
        //查询当前审批日志
        ExamineRecordLog recordLog;
        if (ExamineStatusEnum.RECHECK.getStatus().equals(examineBO.getStatus())) {
            //撤回
            recordLog = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                    .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId())
                    .orderByAsc(ExamineRecordLog::getCreateTime)
                    .one();
        } else {
            List<Integer> normalStatus = ExamineStatusEnum.normalStatus();
            LambdaQueryChainWrapper<ExamineRecordLog> chainWrapper = examineRecordLogService.lambdaQuery();
            chainWrapper.eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                    .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId());
            if (normalStatus.contains(examineBO.getStatus())) {
                chainWrapper.and(wrapper -> {
                    wrapper.or(ObjectUtil.isNotEmpty(examineBO.getExamineUserId()), newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineUserId, examineBO.getExamineUserId()));
                    wrapper.or(ObjectUtil.isNotEmpty(examineBO.getUserEmail()), newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineUserEmail, examineBO.getUserEmail()));
                });
            }

            chainWrapper.orderByAsc(ExamineRecordLog::getCreateTime);
            List<ExamineRecordLog> recordLogs = chainWrapper.list();

            List<Integer> noNormalStatus = ExamineStatusEnum.unNormalStatus();

            List<Long> flowIds = recordLogs.stream().map(ExamineRecordLog::getFlowId).collect(Collectors.toList());
            //多重判断外部审批，限时处理无确切审批人员
            if (noNormalStatus.contains(examineBO.getStatus()) && recordLogs.isEmpty()) {
                recordLog = examineRecordLogService.lambdaQuery()
                        .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId())
                        .orderByDesc(ExamineRecordLog::getExamineTime, ExamineRecordLog::getSort)
                        .one();
            } else if (CollectionUtil.isNotEmpty(flowIds)) {
                ExamineFlowFinal finalFlow = examineFlowFinalService.lambdaQuery().
                        eq(ExamineFlowFinal::getRecordId, examineBO.getRecordId())
                        .in(ExamineFlowFinal::getFlowId, flowIds)
                        .orderByAsc(ExamineFlowFinal::getSort).one();
                if (ObjectUtil.isEmpty(finalFlow)) {
                    recordLog = CollectionUtil.getFirst(recordLogs);
                } else {
                    List<ExamineRecordLog> recordLogList = recordLogs.stream()
                            .filter(item -> item.getFlowId().equals(finalFlow.getFlowId()))
                            .filter(item -> (ObjectUtil.isNotEmpty(item.getExamineUserId()) && ObjectUtil.isNotEmpty(examineBO.getExamineUserId()) && item.getExamineUserId().equals(examineBO.getExamineUserId()))
                                    || (ObjectUtil.isNotEmpty(item.getExamineUserEmail()) && ObjectUtil.isNotEmpty(examineBO.getUserEmail()) && item.getExamineUserEmail().equals(examineBO.getUserEmail()))
                            )
                            .collect(Collectors.toList());
                    if (CollectionUtil.isEmpty(recordLogList)) {
                        recordLog = CollectionUtil.getFirst(recordLogs);
                    } else {
                        recordLog = CollectionUtil.getFirst(recordLogList);
                    }
                }
            } else {
                recordLog = CollectionUtil.getFirst(recordLogs);
            }
        }
        // 判断当前审核是否合法
        if (recordLog == null) {
            //查询最近一条数据，管理员代审核
            recordLog = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId())
                    .orderByAsc(ExamineRecordLog::getCreateTime)
                    .one();
            if (ObjectUtil.isEmpty(recordLog)) {
                return;
            }
            recordLog.setExamineUserId(examineBO.getExamineUserId());
        }
        if (Arrays.asList(ExamineStatusEnum.RECHECK.getStatus(), ExamineStatusEnum.INVALID.getStatus(), ExamineStatusEnum.END.getStatus(), ExamineStatusEnum.ARCHIVE.getStatus()).contains(examineBO.getStatus())
                || (recordLog.getExamineUserId().equals(userInfo.getUserId()) && !Arrays.asList(ExamineStatusEnum.AWAIT.getStatus(), ExamineStatusEnum.UNDERWAY.getStatus()).contains(recordLog.getExamineStatus()))) {
            //处理审批人撤回、作废、终止、归档
            ExamineFlowFinalOptional flowFinalOptional = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId())
                    .eq(ExamineFlowFinalOptional::getFlowId, recordLog.getFlowId()).orderByDesc(ExamineFlowFinalOptional::getSort)
                    .last(" limit 1").one();
            if (flowFinalOptional == null) {
                //因为自动审批节点可能为空
                flowFinalOptional = new ExamineFlowFinalOptional();
                flowFinalOptional.setRecordId(recordLog.getRecordId());
                flowFinalOptional.setType(recordLog.getType());
                flowFinalOptional.setFlowId(recordLog.getFlowId());
                flowFinalOptional.setCreateUserId(userInfo.getUserId());
                flowFinalOptional.setCreateTime(new Date());
            }
            flowFinalOptional.setId(null);
            flowFinalOptional.setUserId(userInfo.getUserId());
            flowFinalOptional.setSort(flowFinalOptional.getSort() == null ? 0 : flowFinalOptional.getSort() + 1);
            examineFlowFinalOptionalService.save(flowFinalOptional);

            recordLog.setLogId(null);
            recordLog.setExamineUserId(userInfo.getUserId());
            recordLog.setExamineUserEmail(null);
            recordLog.setExamineStatus(examineBO.getStatus());
            recordLog.setExamineTime(LocalDateTime.now());
            recordLog.setCreateTime(LocalDateTime.now());
            recordLog.setSort(recordLog.getSort() + 1);
            recordLog.setRemarks(examineBO.getRemarks());
            recordLog.setPassFlag(null);
            recordLog.setRelTarget(null);
            examineRecordLogService.save(recordLog);
        }

        boolean isUser = recordLog.getCreateUserId().equals(userInfo.getUserId());
        boolean isRole = userInfo.getRoles().contains(recordLog.getExamineRoleId());
        boolean isRecheck = ExamineStatusEnum.RECHECK.getStatus().equals(examineBO.getStatus());
        ExamineAdvancedConfig advancedConfig = examineAdvancedConfigService.lambdaQuery().eq(ExamineAdvancedConfig::getExamineId, examineRecord.getExamineId())
                .one();

        /*
         * todo 超级审批最终流程没有角色id这块儿可能要改
         */
        if (isRecheck && (!isUser && !isRole) && !advancedConfig.getIsCreateUserWithdraw()) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_AUTH_ERROR);
        }
        recordLog.setRemarks(examineBO.getRemarks());
        // 查询当前审批记录
        ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
        // 校验审核状态是否合法
        moduleService.checkStatus(examineRecord.getLabel(), examineRecord.getTypeId(), examineBO.getStatus(), examineRecord.getExamineStatus());
        if (!examineBO.getAuditPassFlag().equals(0)) {
            recordLog.setPassFlag(examineBO.getAuditPassFlag());
        }

        if (ExamineStatusEnum.PASS.getStatus().equals(examineBO.getStatus())) {
            List<ExamineFlowFieldUpdateLog> flowFieldUpdateLogs = examineBO.getFlowFieldUpdateLogs();
            if (CollectionUtil.isNotEmpty(flowFieldUpdateLogs)) {
                for (ExamineFlowFieldUpdateLog flowFieldUpdateLog : flowFieldUpdateLogs) {
                    flowFieldUpdateLog.setCreateTime(now);
                    flowFieldUpdateLog.setExamineId(examineRecord.getExamineId());
                    flowFieldUpdateLog.setTypeId(examineRecord.getTypeId());
                    flowFieldUpdateLog.setFlowId(recordLog.getFlowId());
                    flowFieldUpdateLog.setCreateUserId(userInfo.getUserId());
                }
                examineFlowFieldUpdateLogService.saveBatch(flowFieldUpdateLogs);
            }
        }

        // 当前审批通过则去寻找下一层
        if (ExamineStatusEnum.PASS.getStatus().equals(examineBO.getStatus())) {
            auditExaminePass(recordLog, examineRecord, userInfo, ExaminePassBO.builder().init(false).build(), now);
        } else {
            updateCheckStatus(examineRecord, recordLog, ExamineStatusEnum.valueOf(examineBO.getStatus()), examineBO.getFlowId(), null, null, false);
        }

    }


    /**
     * 审批通过逻辑
     *
     * @param recordLog     审批记录日志
     * @param examineRecord 审批记录
     * @param userInfo      用户信息
     * @param examinePassBO 审批参数
     * @return 审核状态
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Integer auditExaminePass(ExamineRecordLog recordLog, ExamineRecord examineRecord, UserInfo userInfo, ExaminePassBO examinePassBO, LocalDateTime now) {
        //更新待办事项缓存数据
        BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + UserUtil.getUserId().toString());
        //表示当前节点是否为虚拟节点
        boolean empty = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, recordLog.getFlowId()).list().isEmpty();
        //判断当前审批层同级是不是还有没走完的，会签，依次审批需要 1 依次审批 2 会签 3 或签
        if (recordLog.getType() == 1 && recordLog.getExamineStatus() != 15) {
            // 说明当前层级还有人需要审核，本条通过即可，将下层审批设为审核中,无需其他操作
            recordLog.setExamineStatus(ExamineStatusEnum.PASS.getStatus());
            recordLog.setUpdateTime(now);
            recordLog.setExamineTime(now);
            examineRecordLogService.updateById(recordLog);
            if (!empty) {
                //代表当前节点为实际存在节点
                ExamineFlowFinal afterFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getInsertTarget, recordLog.getFlowId())
                        .eq(ExamineFlowFinal::getInsertFlag, 2).eq(ExamineFlowFinal::getRelTargetLogId, recordLog.getLogId()).one();
                if (afterFlowFinal != null) {
                    String batchId = IdUtil.simpleUUID();
                    List<ExamineRecordLog> recordLogs = new ArrayList<>();
                    //表示当前节点审批人有征求他人意见节点（当前节点之后）
                    List<ExamineFlowFinalOptional> examineFlowFinalOptionals = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getFlowId, afterFlowFinal.getFlowId())
                            .eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId()).list();
                    for (ExamineFlowFinalOptional finalOptional : examineFlowFinalOptionals) {
                        ExamineRecordLog examineRecordLog = new ExamineRecordLog();
                        examineRecordLog.setLogId(BaseUtil.getNextId());
                        examineRecordLog.setType(afterFlowFinal.getType());
                        examineRecordLog.setCreateTime(now);
                        examineRecordLog.setExamineTime(now);
                        examineRecordLog.setUpdateTime(null);
                        examineRecordLog.setCreateUserId(UserUtil.getUserId());
                        examineRecordLog.setExamineId(afterFlowFinal.getExamineId());
                        examineRecordLog.setExamineRoleId(0L);
                        //   在这块判断审核人状态，是否有效等
                        examineRecordLog.setExamineUserId(finalOptional.getUserId());
                        if (afterFlowFinal.getType() == 1) {
                            if (examineFlowFinalOptionals.indexOf(finalOptional) == 0) {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                            } else {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                            }
                        } else {
                            examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

                        }
                        if (ObjectUtil.isNotNull(finalOptional.getUserId())) {
                            BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + finalOptional.getUserId().toString());
                        }
                        examineRecordLog.setFlowId(afterFlowFinal.getFlowId());
                        examineRecordLog.setRecordId(afterFlowFinal.getRecordId());
                        examineRecordLog.setSort(finalOptional.getSort());
                        examineRecordLog.setBatchId(batchId);
                        recordLogs.add(examineRecordLog);
                    }
                    examineRecordLogService.saveBatch(recordLogs);
                    return ExamineStatusEnum.UNDERWAY.getStatus();
                }

            }
            ExamineRecordLog examineRecordLog = examineRecordLogService.queryNextExamineRecordLog(recordLog.getBatchId(), recordLog.getSort(), recordLog.getLogId());
            if (examineRecordLog != null) {
                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                examineRecordLog.setExamineTime(now);
                examineRecordLogService.updateById(examineRecordLog);
                //发送邮件审批
                if (StrUtil.isNotBlank(examineRecordLog.getExamineUserEmail())) {
                } else {
                    this.addMessage(examineService.getById(examineRecord.getExamineId()), examineRecordLog, examineRecordLog.getExamineUserId(), examineRecord.getExamineReason(), null);
                }
                //如果是已经转发的记录信息则同意之后不再进行限时处理
                if (ObjectUtil.isEmpty(examineRecordLog.getRelTarget())) {
                    //09 添加新增的 现时处理逻辑  插入 更新
                    examineRecordLimitService.addOrUpdateRecordLimit(examineRecord.getRecordId());
                }
                return ExamineStatusEnum.UNDERWAY.getStatus();
            }
        } else if (recordLog.getType() == TWO) {
            // 说明当前层级还有人未审核通过，本条通过即可,无需其他操作
            recordLog.setExamineStatus(ExamineStatusEnum.PASS.getStatus());
            recordLog.setExamineTime(now);
            examineRecordLogService.updateById(recordLog);
            if (!empty) {
                //代表当前节点为实际存在节点
                ExamineFlowFinal afterFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getInsertTarget, recordLog.getFlowId())
                        .eq(ExamineFlowFinal::getInsertFlag, 2).eq(ExamineFlowFinal::getRelTargetLogId, recordLog.getLogId()).one();
                if (afterFlowFinal != null) {
                    String batchId = IdUtil.simpleUUID();
                    List<ExamineRecordLog> recordLogs = new ArrayList<>();
                    //表示当前节点审批人有征求他人意见节点（当前节点之后）
                    List<ExamineFlowFinalOptional> examineFlowFinalOptionals = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getFlowId, afterFlowFinal.getFlowId())
                            .eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId()).list();
                    for (ExamineFlowFinalOptional finalOptional : examineFlowFinalOptionals) {
                        ExamineRecordLog examineRecordLog = new ExamineRecordLog();
                        examineRecordLog.setLogId(BaseUtil.getNextId());
                        examineRecordLog.setType(afterFlowFinal.getType());
                        examineRecordLog.setCreateTime(now);
                        examineRecordLog.setExamineTime(now);
                        examineRecordLog.setUpdateTime(null);
                        examineRecordLog.setCreateUserId(UserUtil.getUserId());
                        examineRecordLog.setExamineId(afterFlowFinal.getExamineId());
                        examineRecordLog.setExamineRoleId(0L);
                        //   在这块判断审核人状态，是否有效等
                        examineRecordLog.setExamineUserId(finalOptional.getUserId());
                        if (afterFlowFinal.getType() == 1) {
                            if (examineFlowFinalOptionals.indexOf(finalOptional) == 0) {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                            } else {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                            }
                        } else {
                            examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

                        }
                        if (ObjectUtil.isNotNull(finalOptional.getUserId())) {
                            BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + finalOptional.getUserId().toString());
                        }
                        examineRecordLog.setFlowId(afterFlowFinal.getFlowId());
                        examineRecordLog.setRecordId(afterFlowFinal.getRecordId());
                        examineRecordLog.setSort(finalOptional.getSort());
                        examineRecordLog.setBatchId(batchId);
                        recordLogs.add(examineRecordLog);
                    }
                    examineRecordLogService.saveBatch(recordLogs);
                    return ExamineStatusEnum.UNDERWAY.getStatus();
                }

            }
            ExamineRecordLog examineRecordLog = examineRecordLogService.queryNextExamineRecordLog(recordLog.getBatchId(), null, recordLog.getLogId());
            if (examineRecordLog != null) {
                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                examineRecordLog.setExamineTime(now);
                examineRecordLogService.updateById(examineRecordLog);

                //如果是已经转发的记录信息则同意之后不再进行限时处理
                if (ObjectUtil.isEmpty(examineRecordLog.getRelTarget())) {
                    //09 添加新增的 现时处理逻辑  插入 更新
                    examineRecordLimitService.addOrUpdateRecordLimit(examineRecord.getRecordId());
                }
                //发送邮件审批
                if (StrUtil.isNotBlank(examineRecordLog.getExamineUserEmail())) {
                }
                return ExamineStatusEnum.UNDERWAY.getStatus();
            }

        } else if (recordLog.getExamineStatus() != 15) {
            if (ObjectUtil.isNotEmpty(recordLog.getExamineUserEmail()) && Validator.isEmail(recordLog.getExamineUserEmail())) {
                //邮件审批
                //如果是或签则直接将当前处理人状态设置为请求状态，其余人处理记录直接作废
                boolean update = examineRecordLogService.lambdaUpdate().set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.PASS.getStatus())
                        .set(ExamineRecordLog::getUpdateTime, now)
                        .set(ExamineRecordLog::getExamineTime, now)
                        .set(ExamineRecordLog::getPassFlag, examinePassBO.getPassFlag())
                        .eq(ExamineRecordLog::getBatchId, recordLog.getBatchId())
                        .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                        .eq(ExamineRecordLog::getExamineUserEmail, recordLog.getExamineUserEmail()).update();
                if (update) {
                    examineRecordLogService.lambdaUpdate()
                            .set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.ORINVALID.getStatus())
                            .eq(ExamineRecordLog::getBatchId, recordLog.getBatchId())
                            .ne(ExamineRecordLog::getExamineUserEmail, recordLog.getExamineUserEmail())
                            .in(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus())
                            .update();
                }
            } else {
                boolean update = true;
                if (ObjectUtil.isNotEmpty(userInfo.getUserId())) {
                    //人员审批
                    //如果是或签则直接将当前处理人状态设置为请求状态，其余人处理记录直接作废
                    update = examineRecordLogService.lambdaUpdate().set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.PASS.getStatus())
                            .set(ExamineRecordLog::getUpdateTime, now)
                            .set(ExamineRecordLog::getExamineTime, now)
                            .set(ExamineRecordLog::getRemarks, recordLog.getRemarks())
                            .set(ExamineRecordLog::getPassFlag, examinePassBO.getPassFlag())
                            .eq(ExamineRecordLog::getBatchId, recordLog.getBatchId())
                            .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                            .eq(ExamineRecordLog::getExamineUserId, userInfo.getUserId()).update();
                }
                if (update) {
                    examineRecordLogService.lambdaUpdate()
                            .set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.ORINVALID.getStatus())
                            .eq(ExamineRecordLog::getBatchId, recordLog.getBatchId())
                            .eq(ExamineRecordLog::getFlowId, recordLog.getFlowId())
                            .ne(ExamineRecordLog::getExamineUserId, recordLog.getExamineUserId())
                            .in(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus())
                            .update();
                }
            }
            if (!empty) {
                //代表当前节点为实际存在节点
                ExamineFlowFinal afterFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getInsertTarget, recordLog.getFlowId())
                        .eq(ExamineFlowFinal::getInsertFlag, 2)
                        .eq(ExamineFlowFinal::getRelTargetLogId, recordLog.getLogId()).one();
                if (afterFlowFinal != null) {
                    String batchId = IdUtil.simpleUUID();
                    List<ExamineRecordLog> recordLogs = new ArrayList<>();
                    //表示当前节点审批人有征求他人意见节点（当前节点之后）
                    List<ExamineFlowFinalOptional> examineFlowFinalOptionals = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getFlowId, afterFlowFinal.getFlowId())
                            .eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId()).list();
                    for (ExamineFlowFinalOptional finalOptional : examineFlowFinalOptionals) {
                        ExamineRecordLog examineRecordLog = new ExamineRecordLog();
                        examineRecordLog.setLogId(BaseUtil.getNextId());
                        examineRecordLog.setType(afterFlowFinal.getType());
                        examineRecordLog.setCreateTime(now);
                        examineRecordLog.setExamineTime(now);
                        examineRecordLog.setUpdateTime(null);
                        examineRecordLog.setCreateUserId(UserUtil.getUserId());
                        examineRecordLog.setExamineId(afterFlowFinal.getExamineId());
                        examineRecordLog.setExamineRoleId(0L);
                        //   在这块判断审核人状态，是否有效等
                        examineRecordLog.setExamineUserId(finalOptional.getUserId());
                        if (afterFlowFinal.getType() == 1) {
                            if (examineFlowFinalOptionals.indexOf(finalOptional) == 0) {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                            } else {
                                examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                            }
                        } else {
                            examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

                        }
                        if (ObjectUtil.isNotNull(finalOptional.getUserId())) {
                            BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + finalOptional.getUserId().toString());
                        }
                        examineRecordLog.setFlowId(afterFlowFinal.getFlowId());
                        examineRecordLog.setRecordId(afterFlowFinal.getRecordId());
                        examineRecordLog.setSort(finalOptional.getSort());
                        examineRecordLog.setBatchId(batchId);
                        recordLogs.add(examineRecordLog);
                    }
                    examineRecordLogService.saveBatch(recordLogs);
                    return ExamineStatusEnum.UNDERWAY.getStatus();
                }

            }

        }
        //更新节点修改字段记录
        updateField(recordLog.getFlowId(), examineRecord.getLabel(), examineRecord.getTypeId(), examineRecord.getExamineId());
        //当前审批流程
        ExamineFlow flow = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, recordLog.getFlowId()).one();
        //处理虚拟节点前后问题审批
        //下一节点
        Map<String, Boolean> map = new HashMap<>();
        map.put("ceaseNext", false);
        ExamineFlow examineFlow = examineRecordNextFlowIsEnds(empty, recordLog, examineRecord, flow, map);
        if (map.get("ceaseNext") && examineFlow == null) {
            return ExamineStatusEnum.PASS.getStatus();
        }
        //下一层审批流程
        if (examineFlow == null) {
            //说明已经是最后一层了，直接通过
            updateCheckStatus(examineRecord, recordLog, ExamineStatusEnum.valueOf(ExamineStatusEnum.PASS.getStatus()), null, examinePassBO.getDataMap(), null, examinePassBO.getInit());
            //判断是否是关联的流程类型,执行完此流程，需要执行父级流程逻辑
            examineFlowBindLabelService.doParentFlow(examineRecord,flow);
            return ExamineStatusEnum.PASS.getStatus();
        } else {
            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());
            examineFlow = examineTypeService.getAvailableFlow(examineFlow, examineRecord, examinePassBO.getDataMap());
            examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());
            JSONObject results = examineTypeService.disposeFlow(examineFlow, examineRecord.getRecordId(), examinePassBO.getDataMap(), null, examinePassBO.getInit());
            //处理流程委托
            examineDelegateService.disposeDelegate(examineFlow.getFlowId(), examineRecord.getRecordId(), examineRecord.getLabel());
            Integer status = examineTypeService.handleRecordLogByAdvancedConfig(examineRecord.getRecordId(), examineFlow.getFlowId(), examinePassBO.getInit(), examinePassBO.getDataMap());
            results.putOpt("status", status);
            // 发送通知
            List<ExamineRecordLog> recordLogs = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                    .eq(ExamineRecordLog::getFlowId, examineFlow.getFlowId())
                    .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                    .list();
            Examine examine = examineService.getById(examineRecord.getExamineId());
            for (ExamineRecordLog examineRecordLog : recordLogs) {
                if (ObjectUtil.isNotEmpty(examineRecordLog.getExamineUserEmail())) {
                } else {
                    this.addMessage(examine, examineRecordLog, examineRecord.getCreateUserId(), examineRecord.getExamineReason(), null);
                }
            }
            return results.getInt("status");
        }
    }



    @Transactional
    public ExamineFlow examineRecordNextFlowIsEnds(boolean empty, ExamineRecordLog recordLog, ExamineRecord examineRecord, ExamineFlow flow, Map<String, Boolean> map) {
        //跳转下一节点
        if (empty) {
            //是虚拟节点
            //当前正在进行虚拟节点
            ExamineFlowFinal beforeFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, recordLog.getFlowId())
                    .eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).one();

            Long relTargetLogId = beforeFlowFinal.getRelTargetLogId();
            //当前虚拟节点关联的节点flowId
            Long insertTarget = beforeFlowFinal.getInsertTarget();
            Integer insertFlag = beforeFlowFinal.getInsertFlag();

            if (insertFlag == 1) {
                //插入之前
                //关联节点下的国有log
                List<ExamineRecordLog> insertTargetList = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getFlowId, insertTarget).eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                        .list();
                ExamineFlowFinal flowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, insertTarget).eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).one();

                insertTargetList.forEach(examineRecordLog -> {
                    if (flowFinal.getType() == 3 && examineRecordLog.getExamineStatus().equals(ExamineStatusEnum.AWAIT.getStatus())) {
                        examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                        examineRecordLog.setExamineTime(LocalDateTime.now());
                        BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + examineRecordLog.getExamineUserId().toString());

                    } else if (relTargetLogId.equals(examineRecordLog.getLogId())
                            && examineRecordLog.getExamineStatus().equals(ExamineStatusEnum.AWAIT.getStatus())) {
                        examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                        examineRecordLog.setExamineTime(LocalDateTime.now());
                        BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + examineRecordLog.getExamineUserId().toString());
                    }
                });
                examineRecordLogService.updateBatchById(insertTargetList);
                map.put("ceaseNext", true);
                return null;
            } else {
                //插入之后
                //关联审批节点
                ExamineFlowFinal associationFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, insertTarget).eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).one();
                //关联节点下的所有log
                List<ExamineRecordLog> associationLogList = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getFlowId, insertTarget).eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                        .list();
                //关联审批节点下的所有待审批与审核中的log
                List<ExamineRecordLog> logList = associationLogList.stream().filter(Objects::nonNull).filter(examineRecordLog -> Arrays.asList(ExamineStatusEnum.AWAIT.getStatus(), ExamineStatusEnum.UNDERWAY.getStatus()).contains(examineRecordLog.getExamineStatus())).collect(Collectors.toList());
                if (logList.size() > 0) {
                    //需要返回虚拟节点的上一节点某个log

                    Map<Long, ExamineRecordLog> logMap = associationLogList.stream().collect(Collectors.toMap(ExamineRecordLog::getLogId, Function.identity()));
                    //当前虚拟审批节点关联log
                    ExamineRecordLog examineRecordLog = logMap.get(beforeFlowFinal.getRelTargetLogId());
                    if (associationFlowFinal.getType() == 3) {
                        ExamineFlow one = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, insertTarget).one();
                        return getNextFlow(one);
                    } else if (associationFlowFinal.getType() == 1) {
                        ExamineRecordLog underwayRecordLog = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                                .eq(ExamineRecordLog::getFlowId, examineRecordLog.getFlowId()).gt(ExamineRecordLog::getSort, examineRecordLog.getSort())
                                .orderByAsc(ExamineRecordLog::getSort).one();
                        underwayRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                        underwayRecordLog.setExamineTime(LocalDateTime.now());
                        examineRecordLogService.updateById(underwayRecordLog);
                        map.put("ceaseNext", true);
                        return null;

                    } else {
                        examineRecordLogService.lambdaUpdate().set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                                .eq(ExamineRecordLog::getExamineTime, LocalDateTime.now())
                                .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.AWAIT.getStatus())
                                .eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId()).update();
                        map.put("ceaseNext", true);
                        return null;
                    }

                } else {
                    //插入之后
                    ExamineFlow one = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, insertTarget).one();
                    return getNextFlow(one);
                }
            }
        } else {
            //不是虚拟节点
            //当前正在审批的虚拟节点之后是否有节点
            ExamineFlowFinal afterFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getInsertTarget, recordLog.getFlowId())
                    .eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).eq(ExamineFlowFinal::getInsertFlag, 2).one();
            List<ExamineRecordLog> afterLogList = new ArrayList<>();
            if (afterFinal != null) {
                afterLogList = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getFlowId, afterFinal.getFlowId())
                        .eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId()).list();
            }

            if (Objects.nonNull(afterFinal) && Objects.nonNull(afterFinal.getInsertFlag()) && afterLogList.size() == 0) {
                //在某节点之前(后)的节点
                //在某节点之前(后)的节点
                Long insertTarget = afterFinal.getFlowId();

                //虚拟节点
                //表示后面还有插入审批节点
                List<ExamineFlowFinalOptional> userList = examineFlowFinalOptionalService.lambdaQuery().eq(ExamineFlowFinalOptional::getFlowId, insertTarget).eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId()).list();
                String batchId = IdUtil.simpleUUID();
                List<ExamineRecordLog> recordLogs = new ArrayList<>();
                for (ExamineFlowFinalOptional examineFlowFinalUser : userList) {
                    ExamineRecordLog examineRecordLog = new ExamineRecordLog();
                    examineRecordLog.setType(examineFlowFinalUser.getType());
                    examineRecordLog.setCreateTime(LocalDateTimeUtil.now());
                    examineRecordLog.setUpdateTime(null);
                    examineRecordLog.setCreateUserId(UserUtil.getUserId());
                    examineRecordLog.setExamineId(examineRecord.getExamineId());
                    examineRecordLog.setExamineRoleId(0L);
                    //   在这块判断审核人状态，是否有效等
                    examineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
                    if (examineFlowFinalUser.getType() == 1) {
                        if (userList.indexOf(examineFlowFinalUser) == 0) {
                            examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                        } else {
                            examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                        }
                    } else {
                        examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

                    }
                    if (ObjectUtil.isNotNull(examineFlowFinalUser.getUserId())) {
                        BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + examineFlowFinalUser.getUserId().toString());
                    }
                    examineRecordLog.setFlowId(examineFlowFinalUser.getFlowId());
                    examineRecordLog.setRecordId(examineRecord.getRecordId());
                    examineRecordLog.setSort(examineFlowFinalUser.getSort());
                    examineRecordLog.setBatchId(batchId);
                    examineRecordLog.setExamineTime(LocalDateTime.now());
                    recordLogs.add(examineRecordLog);
                }
                examineRecordLogService.saveBatch(recordLogs);
                map.put("ceaseNext", true);
                return null;

            } else {
                return getNextFlow(flow);
            }
        }

    }

    private void updateField(Long flowId, Integer label, Long typeId, Long examineId) {

        List<ExamineFlowFieldUpdateLog> list = examineFlowFieldUpdateLogService.lambdaQuery().eq(ExamineFlowFieldUpdateLog::getTypeId, typeId)
                .eq(ExamineFlowFieldUpdateLog::getFlowId, flowId)
                .eq(ExamineFlowFieldUpdateLog::getExamineId, examineId)
                .list();

        if (CollectionUtil.isNotEmpty(list)) {
            List<com.alibaba.fastjson.JSONObject> jsonObjects = new ArrayList<>();
            for (ExamineFlowFieldUpdateLog examineFlowFieldUpdateLog : list) {
                jsonObjects.add(new com.alibaba.fastjson.JSONObject(BeanUtil.beanToMap(examineFlowFieldUpdateLog)));
            }

            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(label).getServerName());

            ExamineUpdateFieldBO examineUpdateFieldBO = new ExamineUpdateFieldBO();
            examineUpdateFieldBO.setLabel(label);
            examineUpdateFieldBO.setTypeId(typeId);
            examineUpdateFieldBO.setData(jsonObjects);
            moduleService.updateFieldInfo(examineUpdateFieldBO);
        }
    }


    /**
     * 修改审核状态
     *
     * @param examineRecord    审核记录
     * @param examineRecordLog 当层审核记录
     * @param statusEnum       状态枚举
     */
    private void updateCheckStatus(ExamineRecord examineRecord, ExamineRecordLog examineRecordLog, ExamineStatusEnum statusEnum, Long flowId, Object data, Integer isSendMessage, boolean isFist) {

        if ((ExamineStatusEnum.RESTORE.equals(statusEnum) || ExamineStatusEnum.REJECT.equals(statusEnum)) && flowId != null) {

            List<Long> managerUserIds = examineManagerUserService.queryExamineUser(examineRecord.getExamineId());
            if (ExamineStatusEnum.RESTORE.equals(statusEnum) && managerUserIds.contains(UserUtil.getUserId())) {
                throw new CrmException(ExamineCodeEnum.EXAMINE_NOT_ADMIN_USER_ERROR);
            }

            List<ExamineReturnFlowVO> flowVOList = examineRecordLogService.queryRecordFlowLog(examineRecord.getRecordId(), false);
            List<ExamineReturnFlowVO> returnFlowVOS = flowVOList.stream().filter(examineReturnFlowVO -> ObjectUtil.isNotNull(examineReturnFlowVO.getFlowId())).collect(Collectors.toList());
            //保留的流程节点
            List<Long> flowIdList = new ArrayList<>();
            for (ExamineReturnFlowVO returnFlowVO : returnFlowVOS) {
                if (ObjectUtil.equal(returnFlowVO.getFlowId(), flowId)) {
                    break;
                }
                flowIdList.add(returnFlowVO.getFlowId());
            }

            BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + UserUtil.getUserId().toString());

            List<Long> deleteCollect = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId())
                    .list().stream().filter(examineFlowFinal -> !flowIdList.contains(examineFlowFinal.getFlowId()) && !flowIdList.contains(examineFlowFinal.getInsertTarget())).map(ExamineFlowFinal::getFlowId).collect(Collectors.toList());


            examineFlowFinalOptionalService.lambdaUpdate()
                    .in(ExamineFlowFinalOptional::getFlowId, deleteCollect)
                    .eq(ExamineFlowFinalOptional::getRecordId, examineRecord.getRecordId())
                    .remove();

            //删除对应外部联系人审批
            LambdaUpdateWrapper<ExamineRecordEmail> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(ExamineRecordEmail::getRecordId, examineRecord.getRecordId());
            updateWrapper.in(ExamineRecordEmail::getFlowId, deleteCollect);
            superExamineEmailService.remove(updateWrapper);

            //删除审批流程
            examineFlowFinalService.lambdaUpdate().eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).in(ExamineFlowFinal::getFlowId, deleteCollect).remove();
            //删除节点关联的log
            List<ExamineRecordLog> list = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                    .in(ExamineRecordLog::getFlowId, deleteCollect)
                    .ne(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.CREATE.getStatus())
                    .ne(ExamineRecordLog::getFlowId, 0L)
                    .list();
            LocalDateTime now = LocalDateTimeUtil.now();
            for (ExamineRecordLog recordLog : list) {
                if (ListUtil.toList(ExamineStatusEnum.AWAIT.getStatus(), ExamineStatusEnum.UNDERWAY.getStatus()).contains(recordLog.getExamineStatus())) {

                    if (ExamineStatusEnum.RESTORE.equals(statusEnum)) {
                        recordLog.setExamineStatus(ExamineStatusEnum.RESTORE.getStatus());
                        recordLog.setUpdateUserId(UserUtil.getUserId());
                        recordLog.setRemarks(examineRecordLog.getRemarks());
                    } else {
                        if (recordLog.getExamineUserId().equals(UserUtil.getUserId())) {
                            recordLog.setExamineStatus(statusEnum.getStatus());
                            recordLog.setUpdateUserId(UserUtil.getUserId());
                            recordLog.setRemarks(examineRecordLog.getRemarks());
                        } else {
                            recordLog.setExamineStatus(ExamineStatusEnum.INVALID.getStatus());
                        }
                    }
                    recordLog.setExamineTime(now);
                    recordLog.setUpdateTime(now);
                }
                Long flowId1 = recordLog.getFlowId();
                recordLog.setFlowId(0L);
                recordLog.setRelTargetFlowId(flowId1);
            }

            //修改审批记录状态
            examineRecordLogService.updateBatchById(list);
            //删除字段记录修改
            examineFlowFieldUpdateLogService.lambdaUpdate().eq(ExamineFlowFieldUpdateLog::getTypeId, examineRecord.getTypeId())
                    .in(ExamineFlowFieldUpdateLog::getFlowId, deleteCollect).remove();

            //当前跳转审批流程
            ExamineFlow examineFlow = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, flowId).one();

            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

            examineFlow = examineTypeService.getAvailableFlow(examineFlow, examineRecord, null);

            examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

            examineTypeService.disposeFlow(examineFlow, examineRecord.getRecordId(), data, null, isFist);

            //处理流程委托
            examineDelegateService.disposeDelegate(examineFlow.getFlowId(), examineRecord.getRecordId(), examineRecord.getLabel());

            examineTypeService.handleRecordLogByAdvancedConfig(examineRecord.getRecordId(), examineFlow.getFlowId(), isFist, data);

            Examine examine = examineService.getById(examineRecord.getExamineId());

            ExamineRecordLog recordLog = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId())
                    .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()).one();

            if (ExamineStatusEnum.RESTORE.equals(statusEnum) && examineFlow.getExamineType() != 4) {

                this.addMessage(examine, 6, examineRecordLog, recordLog == null ? examineRecord.getCreateUserId() : recordLog.getExamineUserId(), null, examineRecord.getTypeId(), 1);

            } else if (ExamineStatusEnum.REJECT.equals(statusEnum) && examineFlow.getExamineType() != 4) {

                this.addMessage(examine, 5, examineRecordLog, recordLog == null ? examineRecord.getCreateUserId() : recordLog.getExamineUserId(), null, examineRecord.getTypeId(), 1);

            }

            examineRecordLog.setUpdateUserId(UserUtil.getUserId());

            // 修改审核记录状态
            examineRecord.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
            updateById(examineRecord);
            // 修改关联模块审核状态
            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
            moduleService.updateCheckStatus(examineRecord.getLabel(), examineRecord.getTypeId(), ExamineStatusEnum.UNDERWAY.getStatus(), data);
            return;
        }

        // 修改审核记录状态
        Integer examineStatus = statusEnum.getStatus();
        if (statusEnum.getStatus().equals(ExamineStatusEnum.RESTORE.getStatus())) {
            examineStatus = ExamineStatusEnum.REJECT.getStatus();
        } else if (statusEnum.getStatus().equals(ExamineStatusEnum.SKIP.getStatus())) {
            examineStatus = ExamineStatusEnum.PASS.getStatus();
        }

        examineRecord.setExamineStatus(examineStatus);
        updateById(examineRecord);

        if (!examineRecordLog.getExamineStatus().equals(ExamineStatusEnum.COPY.getStatus())) {
            examineRecordLog.setExamineStatus(statusEnum.getStatus());
            examineRecordLog.setUpdateTime(LocalDateTimeUtil.now());
            examineRecordLog.setExamineTime(LocalDateTimeUtil.now());
            examineRecordLogService.updateById(examineRecordLog);
        } else {
            //最终节点为抄送节点向上查询最新的审批状态为通过的节点log
            ExamineRecordLog passRecordLog = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getRecordId, examineRecordLog.getRecordId())
                    .ne(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.COPY.getStatus())
                    .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.PASS.getStatus()).orderByDesc(ExamineRecordLog::getExamineTime)
                    .last(" limit 1").one();
            if (passRecordLog != null) {
                examineRecordLog = passRecordLog;
            }
        }

        if (Arrays.asList(ExamineStatusEnum.RECHECK.getStatus(), ExamineStatusEnum.INVALID.getStatus(), ExamineStatusEnum.END.getStatus(), ExamineStatusEnum.ARCHIVE.getStatus()).contains(examineStatus)) {
            //删除log表与flow_final_optional
            List<ExamineRecordLog> list = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getBatchId, examineRecordLog.getBatchId())
                    .ne(ExamineRecordLog::getLogId, examineRecordLog.getLogId())
                    .in(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus()).list();
            List<Long> logList = new ArrayList<>(list.size());
            for (ExamineRecordLog recordLog : list) {
                examineFlowFinalOptionalService.lambdaUpdate().eq(ExamineFlowFinalOptional::getFlowId, recordLog.getFlowId())
                        .eq(ExamineFlowFinalOptional::getRecordId, recordLog.getRecordId())
                        .eq(ObjectUtil.equal(recordLog.getExamineUserId(), 0L), ExamineFlowFinalOptional::getEmail, recordLog.getExamineUserEmail())
                        .eq(ExamineFlowFinalOptional::getUserId, recordLog.getExamineUserId()).remove();
                logList.add(recordLog.getLogId());
            }
            if (!logList.isEmpty()) {
                examineRecordLogService.lambdaUpdate().set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.REMOVE.getStatus())
                        .in(ExamineRecordLog::getLogId, logList).update();
//                examineRecordLogService.removeByIds(logList);
            }
        } else {
            // 将其他正在进行中的当前审核设为废弃
            LambdaUpdateChainWrapper<ExamineRecordLog> updateChainWrapper = examineRecordLogService.lambdaUpdate()
                    .eq(ExamineRecordLog::getBatchId, examineRecordLog.getBatchId())
                    .ne(ExamineRecordLog::getLogId, examineRecordLog.getLogId())
                    .in(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus());
            if (examineRecordLog.getType() == 3) {
                updateChainWrapper.set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.ORINVALID.getStatus());
            } else {
                updateChainWrapper.set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.INVALID.getStatus());
            }
            updateChainWrapper.update();
        }

        if (!isFist) {
            // 修改关联模块审核状态
            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
            moduleService.updateCheckStatus(examineRecord.getLabel(), examineRecord.getTypeId(), examineStatus, data);
        }
        Examine examine = examineService.getById(examineRecord.getExamineId());
        if (ExamineStatusEnum.PASS.equals(statusEnum) || ExamineStatusEnum.SKIP.equals(statusEnum)) {
            this.addMessage(examine, 2, examineRecordLog, examineRecord.getCreateUserId(), null, examineRecord.getTypeId(), isSendMessage);
        } else if (ExamineStatusEnum.REJECT.equals(statusEnum)) {
            this.addMessage(examine, 3, examineRecordLog, examineRecord.getCreateUserId(), null, examineRecord.getTypeId(), isSendMessage);
        } else if (ExamineStatusEnum.RESTORE.equals(statusEnum)) {
            this.addMessage(examine, 4, examineRecordLog, examineRecord.getCreateUserId(), null, examineRecord.getTypeId(), isSendMessage);
        }

        //09 清除 限时处理逻辑
        examineRecordLimitService.removeRecordLimit(examineRecord.getRecordId());

        if (CollectionUtil.toList(ExamineStatusEnum.INVALID, ExamineStatusEnum.REJECT, ExamineStatusEnum.RECHECK).contains(statusEnum)) {
            LambdaQueryChainWrapper<ExamineRecordLog> chainWrapper = examineRecordLogService.lambdaQuery();
            chainWrapper.eq(ExamineRecordLog::getRecordId, examineRecord.getRecordId());
            chainWrapper.orderByAsc(ExamineRecordLog::getCreateTime);
            List<ExamineRecordLog> recordLogsAll = chainWrapper.list();

            List<ExamineRecordHistoryLog> examineRecordHistoryLogs = JSON.parseArray(JSON.toJSONString(recordLogsAll), ExamineRecordHistoryLog.class);

            for (ExamineRecordHistoryLog examineRecordHistoryLog : examineRecordHistoryLogs) {
                examineRecordHistoryLog.setLogId(null);
                examineRecordHistoryLog.setTypeId(examineRecord.getTypeId());
            }
            examineRecordHistoryLogService.saveBatch(examineRecordHistoryLogs);

        }

    }


    private List<Long> saveExamineRecordLog(ExamineUserBO examineUserBO, ExamineFlowFinal examineFlow, Long recordId, Long currentUserId) {
        Examine examine = examineService.getById(examineFlow.getExamineId());
        if (ObjectUtil.isEmpty(examineFlow.getExamineId())) {
            examineFlow.setExamineId(examine.getExamineId());
        }
        return saveExamineRecordLog(examine, examineUserBO, examineFlow, recordId, currentUserId, null);
    }

    private List<Long> saveExamineRecordLog(Examine examine, ExamineUserBO examineUserBO, ExamineFlowFinal examineFlowFinal, Long recordId, Long currentUserId, ExamineRecordSaveBO examineRecordSaveBO) {
        // 通过员工审批
        List<ExamineRecordLog> examineRecordLogList = new ArrayList<>();
        int i = 0;
        String batchId = IdUtil.simpleUUID();
        for (ExamineFlowFinalUser examineFlowFinalUser : examineUserBO.getUserList()) {
            ExamineRecordLog examineRecordLog = new ExamineRecordLog();
            examineRecordLog.setType(examineUserBO.getType());
            examineRecordLog.setCreateTime(LocalDateTimeUtil.now());
            examineRecordLog.setUpdateTime(null);
            examineRecordLog.setCreateUserId(currentUserId);
            examineRecordLog.setExamineId(examineFlowFinal.getExamineId());
            examineRecordLog.setExamineRoleId(0L);
            examineRecordLog.setExamineTime(LocalDateTime.now());
            //   在这块判断审核人状态，是否有效等
            examineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
            examineRecordLog.setExamineUserEmail(examineFlowFinalUser.getEmail());
            if (examineUserBO.getType() == 1) {
                if (i == 0) {
                    examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                } else {
                    examineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                }
            } else {
                examineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());

            }
            if (ObjectUtil.isNotNull(examineFlowFinalUser.getUserId())) {
                BaseUtil.getRedis().del(CrmCacheKey.CRM_BACKLOG_NUM_CACHE_KEY + examineFlowFinalUser.getUserId().toString());
            }
            examineRecordLog.setFlowId(examineFlowFinal.getFlowId());
            examineRecordLog.setRecordId(recordId);
            examineRecordLog.setSort(i++);
            examineRecordLog.setBatchId(batchId);

            examineRecordLogService.save(examineRecordLog);
            if (ExamineStatusEnum.UNDERWAY.getStatus().equals(examineRecordLog.getExamineStatus())) {
                examineRecordLogList.add(examineRecordLog);
            }

        }
        String title = null;
        Long typeId = null;
        String examineReason = null;
        Integer isSendMessage = null;
        boolean isUnusual = false;
        if (examineRecordSaveBO != null) {
            title = examineRecordSaveBO.getTitle();
            typeId = examineRecordSaveBO.getTypeId();
            examineReason = examineRecordSaveBO.getExamineReason();
            isSendMessage = examineRecordSaveBO.getIsSendMessage();
        } else {
            isUnusual = true;
        }
        for (ExamineRecordLog examineRecordLog : examineRecordLogList) {
            if (ExamineStatusEnum.UNDERWAY.getStatus().equals(examineRecordLog.getExamineStatus())) {
                if (ObjectUtil.isNotEmpty(examineRecordLog.getExamineUserId())) {
                    this.addMessage(examine, 1, title, typeId, examineRecordLog, examineRecordLog.getExamineUserId(), isUnusual, examineReason, isSendMessage);
                } else {
                    //todo 发送邮件
                    if (StringUtils.isNotEmpty(examineRecordLog.getExamineUserEmail())) {
                    }
                }
            }
        }

        //09 添加新增的 现时处理逻辑  插入 更新
        examineRecordLimitService.addOrUpdateRecordLimit(recordId);
        return examineRecordLogList.stream().map(ExamineRecordLog::getLogId).collect(Collectors.toList());

    }


    /**
     * 发送审核通知
     *
     * @param examine     examine
     * @param examineType 审核通知类型  1 待审核 2 通过 3 拒绝 4 恢复
     * @param examineLog  examineLog
     * @param userId      userId
     * @date 2020/12/21 17:18
     **/
    private void addMessage(Examine examine, Integer examineType, ExamineRecordLog examineLog, Long userId, String examineReason, Long typeId, Integer isSendMessage) {
        this.addMessage(examine, examineType, null, typeId, examineLog, userId, false, examineReason, isSendMessage);
    }

    /**
     * 依次审批专用
     */
    @Override
    public void addMessage(Examine examine, ExamineRecordLog examineLog, Long userId, String examineReason, Integer isSendMessage) {
        this.addMessage(examine, 1, null, null, examineLog, userId, true, examineReason, isSendMessage);
    }


    @Override
    public void addMessage(Examine examine, Integer examineType, String title, Long typeId, ExamineRecordLog examineLog, Long userId, boolean isUnusual, String examineReason, Integer isSendMessage) {
        int four = 4;
        int five = 5;
        int six = 6;
        int seven = 7;
        int eight = 8;
        int nine = 9;
        int oneZero = 10;
        int oneOne = 11;
        int oneTwo = 12;
        int oneThree = 13;
        if (examine != null) {
            if (ListUtil.toList(1, TWO, THREE, five, six, seven, eight, nine, oneZero, oneOne, oneTwo, TWENTY, oneThree).contains(examine.getLabel())) {
                if (examineType == 1 && !isUnusual) {
                    //正常通过
                    this.addMessageForNewExamine(examine.getLabel(), examineType, title, typeId, examineLog, userId, examineReason);
                } else if (examineType == TWO || examineType == THREE || isUnusual || examineType == 4 || examineType == 5 || examineType == 6) {
                    ExamineMessageBO examineMessageBO = new ExamineMessageBO();
                    examineMessageBO.setCategoryType(examine.getLabel());
                    examineMessageBO.setExamineType(examineType);
                    com.kakarote.core.feign.examine.entity.ExamineRecordLog examineRecordLog =
                            new com.kakarote.core.feign.examine.entity.ExamineRecordLog();
                    BeanUtil.copyProperties(examineLog, examineRecordLog);
                    examineMessageBO.setExamineLog(examineRecordLog);
                    examineMessageBO.setOwnerUserId(userId);
                    examineMessageBO.setTypeId(typeId);
                    examineMessageBO.setIsSendMessage(isSendMessage);
                }
            } else if (Objects.equals(four, examine.getLabel())) {
                this.addHrmMessageForNewExamine(examineType, examineLog, userId);
            } else if (Objects.equals(0, examine.getLabel())) {
                ExamineRecord examineRecord = this.getById(examineLog.getRecordId());
                if (examineRecord == null) {
                    return;
                }
                AdminMessageBO adminMessageBO = new AdminMessageBO();
                if (examineType == 1) {
                    adminMessageBO.setUserId(examineRecord.getCreateUserId());
                    adminMessageBO.setTitle(examine.getExamineName());
                    adminMessageBO.setTypeId(examineRecord.getTypeId());
                    adminMessageBO.setMessageType(AdminMessageEnum.OA_EXAMINE_NOTICE.getType());
                    if (ExamineStatusEnum.COPY.getStatus().equals(examineLog.getExamineStatus())) {
                        examineFlowFinalService.setCopyMessageType(adminMessageBO, examine.getLabel());
                    }
                    adminMessageBO.setIds(Collections.singletonList(examineLog.getExamineUserId()));

                } else if (examineType == TWO || examineType == THREE || examineType == 4 || examineType == 5 || examineType == 6) {

                    if (ObjectUtil.isEmpty(examineLog.getExamineUserId())) {
                        return;
                    }
                    adminMessageBO.setUserId(examineLog.getExamineUserId());
                    adminMessageBO.setUserEmail(examineLog.getExamineUserEmail());
                    if (examine.getLabel().equals(0)) {
                        Integer type;
                        if (examineType == 2) {
                            type = AdminMessageEnum.OA_EXAMINE_PASS.getType();
                            adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
                        } else if (examineType == 3) {
                            type = AdminMessageEnum.OA_EXAMINE_REJECT.getType();
                            adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
                        } else if (examineType == 4) {
                            type = AdminMessageEnum.OA_EXAMINE_RESTORE.getType();
                            adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
                        } else if (examineType == 5) {
                            type = AdminMessageEnum.OA_UNDERWAY_EXAMINE_REJECT.getType();
                            adminMessageBO.setIds(Collections.singletonList(userId));
                        } else if (examineType == 6) {
                            type = AdminMessageEnum.OA_UNDERWAY_EXAMINE_RESTORE.getType();
                            adminMessageBO.setIds(Collections.singletonList(userId));
                        } else {
                            type = AdminMessageEnum.OA_END_EXAMINE_RESTORE.getType();
                            adminMessageBO.setIds(Collections.singletonList(userId));
                        }
                        adminMessageBO.setMessageType(type);
                    } else {
                        if (ExamineStatusEnum.COPY.getStatus().equals(examineLog.getExamineStatus())) {
                            examineFlowFinalService.setCopyMessageType(adminMessageBO, examine.getLabel());
                        }
                    }

                    adminMessageBO.setContent(examineLog.getRemarks());
                    adminMessageBO.setTitle(examine.getExamineName());
                    adminMessageBO.setTypeId(examineRecord.getTypeId());
                }
                if (adminMessageBO.getIds().size() > 0) {
                    AdminMessageService messageService = ApplicationContextHolder.getBean(AdminMessageService.class);
                    log.info("@@@@@@@@@@@@@@@@@@@:{}", JSONUtil.toJsonStr(adminMessageBO));
                    messageService.sendMessage(adminMessageBO);
                }
            }
        }
    }

    /**
     * 人资审核发送通知
     */
    private void addHrmMessageForNewExamine(Integer examineType, ExamineRecordLog examineLog, Long userId) {
        ExamineRecord examineRecord = this.getById(examineLog.getRecordId());
        if (examineRecord == null) {
            return;
        }
        HrmSalaryMonthRecord salaryMonthRecord = salaryRecordService.querySalaryRecordById(examineRecord.getTypeId()).getData();
        if (salaryMonthRecord == null) {
            return;
        }
        AdminMessageBO adminMessageBO = new AdminMessageBO();
        if (examineType == 1) {

            adminMessageBO.setUserId(userId);
            adminMessageBO.setTitle(salaryMonthRecord.getYear() + "-" + salaryMonthRecord.getMonth() + "");
            adminMessageBO.setTypeId(examineRecord.getTypeId());
            adminMessageBO.setUserEmail(examineLog.getExamineUserEmail());
            adminMessageBO.setMessageType(AdminMessageEnum.HRM_EMPLOYEE_SALARY_EXAMINE.getType());
            adminMessageBO.setIds(Collections.singletonList(examineLog.getExamineUserId()));
        } else if (examineType == TWO || examineType == THREE || examineType == 4 || examineType == 5 || examineType == 6) {
            adminMessageBO.setTypeId(examineRecord.getTypeId());
            adminMessageBO.setUserId(examineLog.getExamineUserId());
            adminMessageBO.setUserEmail(examineLog.getExamineUserEmail());
            adminMessageBO.setTitle(salaryMonthRecord.getYear() + "-" + salaryMonthRecord.getMonth() + "");
            adminMessageBO.setContent(examineLog.getRemarks());
            Integer type;
            if (examineType == 2) {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_PASS.getType();
                adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
            } else if (examineType == 3) {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_REJECT.getType();
                adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
            } else if (examineType == 4) {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_RESTORE.getType();
                adminMessageBO.setIds(Collections.singletonList(examineRecord.getCreateUserId()));
            } else if (examineType == 5) {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_UNDERWAY_REJECT.getType();
                adminMessageBO.setIds(Collections.singletonList(userId));
            } else if (examineType == 6) {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_UNDERWAY_RESTORE.getType();
                adminMessageBO.setIds(Collections.singletonList(userId));
            } else {
                type = AdminMessageEnum.HRM_EMPLOYEE_SALARY_END_RESTORE.getType();
                adminMessageBO.setIds(Collections.singletonList(userId));
            }
            adminMessageBO.setMessageType(type);
        }
        if (adminMessageBO.getIds() != null && adminMessageBO.getIds().size() > 0) {
            AdminMessageService messageService = ApplicationContextHolder.getBean(AdminMessageService.class);
            messageService.sendMessage(adminMessageBO);
        }
    }

    /**
     * 发送待审核通知 客户与进销存模块
     */
    private void addMessageForNewExamine(Integer categoryType, Integer examineType, String title, Long typeId, ExamineRecordLog examineLog, Long ownerUserId, String examineReason) {
        AdminMessageBO adminMessageBO = new AdminMessageBO();
        adminMessageBO.setUserId(ownerUserId);
        if (examineType == 1) {
            if (categoryType == 1) {
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_CONTRACT_EXAMINE.getType());
            } else if (categoryType == TWO) {
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_RECEIVABLES_EXAMINE.getType());
            } else if (categoryType == THREE) {
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_INVOICE_EXAMINE.getType());
            } else if (categoryType == TWENTY) {
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_FLOW_EXPORT.getType());
            } else {
                this.addMessageByExamine(categoryType, title, typeId, adminMessageBO, examineReason);
            }
            adminMessageBO.setIds(Collections.singletonList(examineLog.getExamineUserId()));
        }
        if (adminMessageBO.getIds() != null && adminMessageBO.getIds().size() > 0) {
            AdminMessageService messageService = ApplicationContextHolder.getBean(AdminMessageService.class);
            messageService.sendMessage(adminMessageBO);
        }

    }

    /**
     * 补充消息详情
     *
     * @param categoryType   categoryType
     * @param adminMessageBO adminMessageBO
     * @date 2020/9/7 15:22
     **/
    private void addMessageByExamine(Integer categoryType, String title, Long typeId, AdminMessageBO adminMessageBO, String examineReason) {
        switch (categoryType) {
            case 5: {
                //采购订单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_PURCHASE_EXAMINE.getType());
                break;
            }
            case 6: {
                //采购退货单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_RETREAT_EXAMINE.getType());
                break;
            }
            case 7: {
                //销售订单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_SALE_EXAMINE.getType());
                break;
            }
            case 8: {
                //销售退货单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_SALE_RETURN_EXAMINE.getType());
                break;
            }
            case 9: {
                //付款单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_PAYMENT_EXAMINE.getType());
                break;
            }
            case 10: {
                //回款单
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_COLLECTION_EXAMINE.getType());
                break;
            }
            case 11: {
                //盘点
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_INVENTORY_EXAMINE.getType());
                break;
            }
            case 12: {
                //调拨
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setMessageType(AdminMessageEnum.JXC_ALLOCATION_EXAMINE.getType());
                break;
            }
            case 13: {
                // 客户团队成员审批提醒
                adminMessageBO.setTitle(title);
                adminMessageBO.setTypeId(typeId);
                adminMessageBO.setExamineReason(examineReason);
                adminMessageBO.setMessageType(AdminMessageEnum.CRM_CUSTOMER_TEAM_WAIT.getType());
                break;
            }
            default:
                break;
        }
    }


    @Override
    public ExamineRecordVO queryExamineRecordList(Long recordId, Long ownerUserId, String outExamineEmail, Integer outExamineStyle) {
        ExamineRecordVO examineRecordVO = new ExamineRecordVO();
        ExamineRecord examineRecord = getById(recordId);
        if (examineRecord == null) {
            return examineRecordVO;
        }
        Integer label = examineRecord.getLabel();
        examineRecordVO.setLabel(label);
        //当前审批人
        Long auditUserId = UserUtil.getUserId();
        //判断是否有撤回权限
        boolean isValidUser = auditUserId.equals(examineRecord.getCreateUserId());
        boolean isNormalStatus = (examineRecord.getExamineStatus().equals(ExamineStatusEnum.AWAIT.getStatus()) || examineRecord.getExamineStatus().equals(ExamineStatusEnum.UNDERWAY.getStatus()));
        if (isValidUser && isNormalStatus) {
            examineRecordVO.setIsRecheck(1);
        } else {
            examineRecordVO.setIsRecheck(0);
        }

        ExaminePreviewBO examinePreviewBO = new ExaminePreviewBO();
        examinePreviewBO.setLabel(label);
        Map<String, Object> dataMap = new HashMap<>(8);
        List<ExamineFlowConditionDataVO> conditionDataVoS = examineService.previewFiledName(examineRecord.getLabel(), null, examineRecord.getExamineId());
        //判断有无条件审核，如果有获取相应数据
        if (conditionDataVoS != null) {
            List<String> fieldList = conditionDataVoS.stream().map(ExamineFlowConditionDataVO::getFieldName).collect(Collectors.toList());
            fieldList.removeIf(StrUtil::isEmpty);
            if (CollUtil.isNotEmpty(fieldList)) {
                ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
                dataMap = moduleService.getConditionMap(label, examineRecord.getTypeId(), recordId);
            } else {
                dataMap.put(ExamineConst.CREATE_USER_ID, examineRecord.getCreateUserId());
            }
        }
        examinePreviewBO.setDataMap(dataMap);
        examinePreviewBO.setStatus(1);
        examinePreviewBO.setRecordId(examineRecord.getRecordId());
        examinePreviewBO.setOwnerUserId(examineRecord.getCreateUserId());
        ExaminePreviewVO examinePreviewVO = examineService.previewExamineFlow(examinePreviewBO);
        List<ExamineFlowVO> examineFlowVoS = examinePreviewVO.getExamineFlowList();
        List<ExamineFlowDataVO> examineFlowDataVoS = new ArrayList<>();
        //发起人详细信息
        SimpleUser createUser = UserCacheUtil.getSimpleUser(examineRecord.getCreateUserId());
        for (ExamineFlowVO examineFlowVO : examineFlowVoS) {
            ExamineFlowDataVO examineFlowDataVO = new ExamineFlowDataVO();
            BeanUtil.copyProperties(examineFlowVO, examineFlowDataVO, "userList");
            examineFlowDataVO.setExamineStatus(examineRecord.getExamineStatus());
            List<ExamineRecordLog> recordLogList = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getRecordId, recordId)
                    .eq(ExamineRecordLog::getFlowId, examineFlowDataVO.getFlowId()).list();
            //判断审批流程是否已通过
            boolean isPass = true;
            //审核通过  记录状态
            Integer status = null;
            if (recordLogList.size() > 0) {
                for (ExamineRecordLog recordLog : recordLogList) {
                    boolean isNoPass = !ExamineStatusEnum.PASS.getStatus().equals(recordLog.getExamineStatus()) && !ExamineStatusEnum.CREATE.getStatus().equals(recordLog.getExamineStatus());
                    if (isNoPass) {
                        isPass = false;
                        break;
                    }
                }
                if (isPass) {
                    status = ExamineStatusEnum.PASS.getStatus();
                }
            }
            List<SimpleUser> userList = examineFlowVO.getFinalUserList();
            List<Map<String, Object>> mapList = new ArrayList<>();
            Integer isEnd = null, breakStatus = null;
            if (CollUtil.isNotEmpty(userList)) {
                for (SimpleUser simpleUser : userList) {
                    Map<String, Object> map = new HashMap<>(6);
                    Long userId = simpleUser.getUserId();
                    map.put("userId", userId);
                    map.put("img", simpleUser.getImg());
                    map.put("realname", simpleUser.getRealname());
                    map.put("outerUserEmail", simpleUser.getOuterUserEmail());
                    List<ExamineRecordLog> examineRecordLogList = examineRecordLogService.lambdaQuery()
                            .eq(ExamineRecordLog::getFlowId, examineFlowVO.getFlowId())
                            .eq(ExamineRecordLog::getRecordId, recordId)
                            .eq(ObjectUtil.isNotEmpty(userId), ExamineRecordLog::getExamineUserId, userId)
                            .eq(ObjectUtil.isNotEmpty(simpleUser.getOuterUserEmail()), ExamineRecordLog::getExamineUserEmail, simpleUser.getOuterUserEmail())
                            .list();
                    if (CollUtil.isNotEmpty(examineRecordLogList)) {
                        Integer examineStatus = examineRecordLogList.get(0).getExamineStatus();
                        map.put("examineStatus", examineStatus);
                        map.put("examineTime", examineRecordLogList.get(0).getUpdateTime());
                        map.put("remarks", examineRecordLogList.get(0).getRemarks());
                        //跳过作废的
                        if (examineStatus == 8) {
                            continue;
                        }
                        //审核进行中或已结束 记录状态
                        if ((examineStatus != 0 && examineStatus != 1) || examineFlowVO.getType() == 3) {
                            isEnd = examineStatus;
                        }
                        //审核结束  记录状态
                        if (ListUtil.toList(2, 4, 5, 7).contains(examineStatus)) {
                            if (examineStatus == 4) {
                                //使用发起人信息填充
                                map.put("userId", createUser.getUserId());
                                map.put("img", createUser.getImg());
                                map.put("realname", createUser.getRealname());
                            }
                            breakStatus = examineStatus;
                        }
                    } else {
                        if (status != null) {
                            map.put("examineStatus", status);
                        } else {
                            map.put("examineStatus", ExamineStatusEnum.AWAIT.getStatus());
                        }
                    }
                    mapList.add(map);
                    //审核结束 终止循环人员信息(对于或签拒绝时会产生无用审核人记录，终止循环可以去除多余信息)
                    if (breakStatus != null) {
                        map.put("examineStatus", breakStatus);
                        break;
                    }
                }
            }
            //审核进行中或已结束 填充当前流程审核状态
            if (isEnd != null) {
                examineFlowDataVO.setExamineStatus(isEnd);
            } else {
                if (examineFlowVO.getType() != 3) {
                    examineFlowDataVO.setExamineStatus(status != null ? status : ExamineStatusEnum.AWAIT.getStatus());
                }
            }
            examineFlowDataVO.setUserList(mapList);
            if (status != null) {
                examineFlowDataVO.setExamineStatus(status);
            }
            examineFlowDataVoS.add(examineFlowDataVO);
            //审核结束 终止循环剩下的流程
            if (breakStatus != null) {
                break;
            }
        }

        examineRecordVO.setCreateUser(createUser);
        //补充创建人节点
        ExamineFlowDataVO examineFlowDataVO = this.supplementExamineFlowDataVO(createUser, examineRecord.getCreateTime());
        examineFlowDataVO.setExamineReason(examineRecord.getExamineReason());
        examineFlowDataVoS.add(0, examineFlowDataVO);
        examineRecordVO.setExamineFlowList(examineFlowDataVoS);
        List<ExamineRecordLog> recordLogs = examineRecordLogService.lambdaQuery()
                .eq(ExamineRecordLog::getRecordId, recordId)
                .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()).list();
        List<Long> examineUserIds = new ArrayList<>();
        List<String> examineEmails = new ArrayList<>();
        if (CollUtil.isNotEmpty(recordLogs)) {
            examineUserIds = recordLogs.stream().map(ExamineRecordLog::getExamineUserId).collect(Collectors.toList());
            examineEmails = recordLogs.stream().map(ExamineRecordLog::getExamineUserEmail).collect(Collectors.toList());
        }
        //----------------------------------
        //0923 添加外部联系人审批过后   禁用掉该外部审批人调用的后续审批接口
        if (ObjectUtil.isNotEmpty(outExamineEmail) && outExamineStyle.equals(2)) {
            List<ExamineRecordLog> checkRecordLogs = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getRecordId, recordId)
                    .eq(ExamineRecordLog::getExamineUserEmail, outExamineEmail)
                    .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()).list();
            if (CollectionUtil.isEmpty(checkRecordLogs)) {
                examineRecordVO.setIsCheck(0);
                examineRecordVO.setIsRecheck(0);
                return examineRecordVO;
            }
        }

        //当前登录人是否有审核权限
        if (examineUserIds.contains(auditUserId) || examineEmails.contains(outExamineEmail)) {
            examineRecordVO.setIsCheck(1);
        } else {
            int isCheck = 0;
            List<Long> longs = adminService.queryNormalUserByIds(examineUserIds).getData();
            if (longs.isEmpty()) {
                Optional<ExamineFlowDataVO> dataVOOptional = examineRecordVO.getExamineFlowList().stream().filter(data -> ExamineStatusEnum.AWAIT.getStatus().equals(data.getExamineStatus())).findFirst();
                if (dataVOOptional.isPresent()) {
                    //查询当前用户在不在审核列表中，用于处理审核人被禁用，超管审核的问题
                    for (Map<String, Object> map : dataVOOptional.get().getUserList()) {
                        if (Objects.equals(ExamineStatusEnum.AWAIT.getStatus(), map.get("examineStatus")) && Objects.equals(auditUserId, map.get("userId"))) {
                            isCheck = 1;
                            break;
                        }
                    }
                }
            }
            examineRecordVO.setIsCheck(isCheck);
        }
        return examineRecordVO;
    }


    /**
     * 增加创建人节点
     *
     * @param simpleUser simpleUser
     * @return com.kakarote.examine.entity.VO.ExamineFlowDataVO
     * @date 2020/12/22 10:33
     **/
    private ExamineFlowDataVO supplementExamineFlowDataVO(SimpleUser simpleUser, LocalDateTime examineTime) {
        ExamineFlowDataVO examineFlowDataVO = new ExamineFlowDataVO();
        examineFlowDataVO.setFlowId(0L);
        examineFlowDataVO.setExamineStatus(ExamineStatusEnum.CREATE.getStatus());
        Map<String, Object> map = new HashMap<>(6);
        Long userId = simpleUser.getUserId();
        map.put("userId", userId);
        map.put("img", simpleUser.getImg());
        map.put("realname", simpleUser.getRealname());
        map.put("examineStatus", ExamineStatusEnum.CREATE.getStatus());
        map.put("examineTime", examineTime);
        List<Map<String, Object>> userList = ListUtil.toList(map);
        examineFlowDataVO.setUserList(userList);
        return examineFlowDataVO;
    }

    @Override
    public ExamineRecordReturnVO queryExamineRecordInfo(Long recordId) {
        ExamineRecordReturnVO examineRecordReturnVO = new ExamineRecordReturnVO();
        ExamineRecord examineRecord = this.getById(recordId);
        if (examineRecord == null) {
            // 从缓存中查询
            String cacheKey = CrmCacheKey.EXAMINE_RECORD_TEMP_CACHE_KEY + recordId;
            String cacheValue = BaseUtil.getRedis().get(cacheKey);
            if (StrUtil.isNotEmpty(cacheValue)) {
                examineRecord = JSON.parseObject(cacheValue, ExamineRecord.class);
            }else{
                log.error("审批记录查询错误，错误的记录id为{}", recordId);
                return examineRecordReturnVO;
            }
        }
        examineRecordReturnVO.setRecordId(recordId);
        examineRecordReturnVO.setTypeId(examineRecord.getTypeId());
        Integer examineStatus = examineRecord.getExamineStatus();
        examineRecordReturnVO.setExamineStatus(examineStatus);
        examineRecordReturnVO.setParentRecordId(examineRecord.getParentRecordId());
        if (examineStatus != 1) {
            List<ExamineRecordLog> recordLogs = examineRecordLogService.lambdaQuery()
                    .eq(ExamineRecordLog::getRecordId, recordId)
                    .eq(ExamineRecordLog::getExamineStatus, examineStatus).list();
            if (CollUtil.isNotEmpty(recordLogs)) {
                List<Long> userIds = recordLogs.stream()
                        .map(ExamineRecordLog::getExamineUserId)
                        .filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
                examineRecordReturnVO.setExamineUserIds(userIds);
            }
        } else {
            examineRecordReturnVO.setExamineUserIds(new ArrayList<>());
        }
        return examineRecordReturnVO;
    }

    @Override
    public Boolean deleteExamineRecord(Long recordId) {
        recordOptionalService.lambdaUpdate().eq(ExamineRecordOptional::getRecordId, recordId).remove();
        examineRecordLogService.lambdaUpdate().eq(ExamineRecordLog::getRecordId, recordId).remove();
        return this.lambdaUpdate().eq(ExamineRecord::getRecordId, recordId).remove();
    }

    @Override
    public Boolean updateExamineRecord(Long recordId, Integer examineStatus) {
        ExamineStatusEnum.valueOf(examineStatus);
        ExamineRecord examineRecord = this.getById(recordId);
        if (examineRecord == null) {
            return false;
        }
        examineRecordLogService.lambdaUpdate()
                .set(ExamineRecordLog::getExamineStatus, examineStatus)
                .eq(ExamineRecordLog::getRecordId, recordId)
                .in(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus());
        /*
         修改审核记录状态
         */
        examineRecord.setExamineStatus(examineStatus);
        return updateById(examineRecord);
    }

    @Override
    public Boolean deleteExamineRecordAndLog(Integer label) {
        List<ExamineRecord> examineRecords = this.lambdaQuery().eq(ExamineRecord::getLabel, label).list();
        if (CollUtil.isNotEmpty(examineRecords)) {
            List<Long> recordIds = examineRecords.stream().map(ExamineRecord::getRecordId).collect(Collectors.toList());
            examineRecordLogService.lambdaUpdate().in(ExamineRecordLog::getRecordId, recordIds).remove();
            this.removeByIds(recordIds);

            //清理新建的examine

        }
        return true;
    }

    @Override
    public List<ExamineVO> recentlyUsedExamineList(Boolean isAdmin, Long userId, Long deptId) {
        List<Long> ids = null;
        if (!isAdmin) {
            QueryParentDeptBO queryBO = new QueryParentDeptBO();
            queryBO.setDeptId(deptId);
            queryBO.setLevel(20);
            ids = adminService.queryParentDeptIdByLevel(queryBO).getData();
            ids.add(deptId);
        }
        return baseMapper.queryRecentlyUsedExamineList(isAdmin, userId, deptId, ids);
    }

    @Transactional
    @Override
    public void forwardOthers(ExamineForwardOthersBO examineForwardOthersBO) {
        ExamineRecordLog curExamineRecordLog = examineRecordLogService.lambdaQuery()
                .and(wrapper -> {
                    wrapper.or(newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineUserId, UserUtil.getUserId()));
                    if (ObjectUtil.isNotEmpty(examineForwardOthersBO.getCurHandlerEmail())) {
                        wrapper.or(newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineUserEmail, examineForwardOthersBO.getCurHandlerEmail()));
                    }
                })
                .eq(ExamineRecordLog::getRecordId, examineForwardOthersBO.getRecordId())
                .eq(ExamineRecordLog::getFlowId, examineForwardOthersBO.getFlowFinalId())
                .eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                .one();
        if (!ExamineStatusEnum.UNDERWAY.getStatus().equals(curExamineRecordLog.getExamineStatus())) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_NO_AUTH);
        }
        ExamineFlowFinalUser examineFlowFinalUser = examineForwardOthersBO.getExamineFlowFinalUser();

        examineRecordLogService.lambdaUpdate()
                .set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.FORWARD.getStatus())
                .set(ExamineRecordLog::getPassFlag, PassFlagEnum.FORWARD_HANDLE.getType())
                .eq(ExamineRecordLog::getLogId, curExamineRecordLog.getLogId()).update();
        curExamineRecordLog.setRelTarget(curExamineRecordLog.getLogId());
        curExamineRecordLog.setLogId(null);
        curExamineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
        curExamineRecordLog.setExamineUserEmail(examineFlowFinalUser.getEmail());
        curExamineRecordLog.setCreateTime(LocalDateTime.now());//其他值不变就修改这几个值
        curExamineRecordLog.setType(curExamineRecordLog.getType());
        curExamineRecordLog.setPassFlag(PassFlagEnum.FORWARD_HANDLE.getType());
        curExamineRecordLog.setHandlerType(ExamineLogHandlerType.FORWARD.getType());

        examineRecordLogService.save(curExamineRecordLog);
        //----------------------------------------------------------------------
        //转他人处理，如果是外部联系人
        if (StringUtils.isNotEmpty(examineFlowFinalUser.getEmail())) {

        }
    }

    @Override
    public void autoForwardOthers(ExamineAutoForwardOthersBO examineForwardOthersBO) {
        ExamineRecord examineRecord = getById(examineForwardOthersBO.getRecordId());
        ExamineRecordLog curExamineRecordLog = examineRecordLogService.getById(examineForwardOthersBO.getRecordLogId());
        //非审核中节点不能转发
        if (!curExamineRecordLog.getExamineStatus().equals(ExamineStatusEnum.UNDERWAY.getStatus())) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_NO_AUTH);
        }
        //校验转发有效人员
        List<Long> userIds = examineForwardOthersBO.getExamineFlowFinalUserList().stream()
                .map(ExamineFlowFinalUser::getUserId)
                .collect(Collectors.toList());
        List<Long> normalUserIds = adminService.queryNormalUserByIds(userIds).getData();
        List<ExamineFlowFinalUser> examineFlowFinalUserList = examineForwardOthersBO.getExamineFlowFinalUserList();
        List<ExamineFlowFinalUser> normalNodeHandleUser = examineForwardOthersBO.getExamineFlowFinalUserList()
                .stream()
                .filter(item -> (ObjectUtil.isNotEmpty(item.getEmail()) || (ObjectUtil.isNotEmpty(normalUserIds) && normalUserIds.contains(item.getUserId()))))
                .collect(Collectors.toList());
        if (ObjectUtil.isEmpty(curExamineRecordLog.getSort())) {
            curExamineRecordLog.setSort(0);
        }
        Integer sort = curExamineRecordLog.getSort() + 1;//todo 这个sort需要修改

        if (CollectionUtil.isNotEmpty(examineFlowFinalUserList)) {
            examineRecordLogService.lambdaUpdate()
                    .set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.FORWARD.getStatus())
                    .set(ExamineRecordLog::getPassFlag, examineForwardOthersBO.getAuditPassFlag())
                    .eq(ExamineRecordLog::getLogId, curExamineRecordLog.getLogId()).update();

            Long relTargetLogId = curExamineRecordLog.getLogId();
            for (int i = 0; i < examineFlowFinalUserList.size(); i++) {
                ExamineFlowFinalUser examineFlowFinalUser = examineFlowFinalUserList.get(i);
                if (ObjectUtil.isNotEmpty(examineFlowFinalUser.getEmail())) {
                    if (!curExamineRecordLog.getExamineUserEmail().equals(examineFlowFinalUser.getEmail())) {
                        throw new CrmException(ExamineCodeEnum.EXAMINE_NO_AUTH);
                    }
                }
                if (examineForwardOthersBO.getType().equals(1)) {
                    if (i == 0) {
                        curExamineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                    } else {
                        curExamineRecordLog.setExamineStatus(ExamineStatusEnum.AWAIT.getStatus());
                    }
                } else {
                    curExamineRecordLog.setExamineStatus(ExamineStatusEnum.UNDERWAY.getStatus());
                }
                curExamineRecordLog.setRelTarget(relTargetLogId);
                curExamineRecordLog.setLogId(null);
                curExamineRecordLog.setExamineUserId(examineFlowFinalUser.getUserId());
                curExamineRecordLog.setExamineUserEmail(examineFlowFinalUser.getEmail());
                curExamineRecordLog.setCreateTime(LocalDateTime.now());//其他值不变就修改这几个值
                curExamineRecordLog.setExamineTime(LocalDateTime.now());
                curExamineRecordLog.setSort(sort);
                curExamineRecordLog.setType(examineForwardOthersBO.getType());
                curExamineRecordLog.setHandlerType(ExamineLogHandlerType.FORWARD.getType());
                if (CollectionUtil.isEmpty(normalNodeHandleUser)) {
                    curExamineRecordLog.setPassFlag(PassFlagEnum.END_AUTO_NO_USER.getType());
                    //设置流程终止
                    updateExamineRecord(examineRecord.getRecordId(), ExamineStatusEnum.END.getStatus());
                    curExamineRecordLog.setExamineStatus(ExamineStatusEnum.END.getStatus());
                    // 修改关联模块审核状态
                    ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
                    moduleService.updateCheckStatus(examineRecord.getLabel(), examineRecord.getTypeId(), ExamineStatusEnum.END.getStatus(), null);
                    examineRecordLogService.save(curExamineRecordLog);
                    break;
                } else {
                    if (normalUserIds.contains(examineFlowFinalUser.getUserId()) || ObjectUtil.isNotEmpty(examineFlowFinalUser.getEmail())) {
                        curExamineRecordLog.setPassFlag(examineForwardOthersBO.getAuditPassFlag());
                        examineRecordLogService.save(curExamineRecordLog);
                        sort++;
                    }
                }
            }
            //如果是已经转发的记录信息则同意之后不再进行限时处理
            if (ObjectUtil.isEmpty(curExamineRecordLog.getRelTarget())) {
                //添加新增的 现时处理逻辑  插入
                examineRecordLimitService.addOrUpdateRecordLimit(examineRecord.getRecordId());
            }
        } else {
            //如果转发人员无效则流程终止
            //设置流程终止
            updateExamineRecord(examineRecord.getRecordId(), ExamineStatusEnum.END.getStatus());
            //设置审批记录终止
            curExamineRecordLog.setExamineStatus(ExamineStatusEnum.END.getStatus());
            examineRecordLogService.updateById(curExamineRecordLog);
            // 修改关联模块审核状态
            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
            moduleService.updateCheckStatus(examineRecord.getLabel(), examineRecord.getTypeId(), ExamineStatusEnum.END.getStatus(), null);

        }
    }

    @Transactional
    @Override
    public void solicitOthers(ExamineFlowFinalBO examineFlowFinalBO) {
        if (examineFlowFinalBO.getUserList().size() == 1) {
            examineFlowFinalBO.setType(1);
        }
        if (ObjectUtil.isEmpty(examineFlowFinalBO.getType())) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_TYPE_NULL_ERROR);
        }
        boolean exists = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, examineFlowFinalBO.getInsertTarget()).exists();

        if (!exists) {
            throw new CrmException(ExamineCodeEnum.EXAMINE_NOT_SEEK_USER_ERROR);
        }

        Long curFlowId = examineFlowFinalBO.getInsertTarget();//插入的目标节点即为 当前待处理节点
        ExamineFlowFinal examineFlow = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getRecordId, examineFlowFinalBO.getRecordId()).eq(ExamineFlowFinal::getFlowId, curFlowId).one();//获取当前处理节点信息
        examineFlowFinalBO.setName("征求他人意见");
        Long insertFlowId = examineService.addExamineFlowFinalNode(examineFlowFinalBO, ExamineFlowFlagEnum.SEEK.getType());//插入的节点
        switch (examineFlowFinalBO.getInsertFlag()) {
            case 1://放在当前节点前，则将当前节点设置为待审核，将征求人节点设置为审核中
                //更新当前处理节点状态为等待审核
                examineRecordLogService.lambdaUpdate()
                        .set(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.AWAIT.getStatus())
                        .eq(ExamineRecordLog::getRecordId, examineFlowFinalBO.getRecordId())
                        .eq(ExamineRecordLog::getFlowId, curFlowId)
                        .and(wrapper -> {
                            wrapper.or(newWrapper -> {
                                newWrapper.eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus());
                            });
                        }).update();
                ExamineRecord examineRecord = getById(examineFlowFinalBO.getRecordId());
                // 找下一层的审核人-由于是征求他人处理，因此此处应该将被征求人设置为处理中
                ExamineUserBO examineUserBO = new ExamineUserBO();
                examineUserBO.setUserList(examineFlowFinalBO.getUserList());
                examineUserBO.setType(examineFlowFinalBO.getType());
                List<ExamineFlowFinalUser> nextUserList = examineUserBO.getUserList();
                if (CollectionUtil.isNotEmpty(nextUserList)) {
                    if (examineUserBO.getExamineFlow() != null) {
                        ExamineFlow examineFlowTmp = examineUserBO.getExamineFlow();
                        BeanUtil.copyProperties(examineFlowTmp, examineFlow);
                    }
                    examineFlow.setExamineId(examineRecord.getExamineId());
                    ExamineFlowFinal examineFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, insertFlowId).one();
                    if (ObjectUtil.isNotEmpty(examineFlowFinal)) {
                        saveExamineRecordLog(examineUserBO, examineFlowFinal, examineRecord.getRecordId(), examineRecord.getCreateUserId());
                    }
                }
                break;
            case 2:
                ExamineBO examineBO = new ExamineBO();
                examineBO.setExamineUserId(UserUtil.getUserId());
                examineBO.setFlowId(curFlowId);
                examineBO.setRemarks("征求他人意见");
                examineBO.setRecordId(examineFlowFinalBO.getRecordId());
                examineBO.setStatus(ExamineStatusEnum.PASS.getStatus());
                auditExamine(examineBO);//如果放在之后则当前层直接通过
                break;
        }
    }

    /**
     * @return
     * @Description 获取个人审批统计表中的数据
     * @Author UNIQUE
     * @Date 2022/8/27
     * @Param
     **/
    @Override
    public BasePage<SuperExamineReportListVO> getSuperExamineReportList(SuperExamineReportSearchBO searchBO) {
        return getBaseMapper().getSuperExamineReportList(searchBO.parse(), searchBO);
    }

    @Override
    public SuperExamineReportHeadVO getExamineReportInfo(SuperExamineReportSearchBO searchBO) {
        List<SuperExamineReportHeadVO> examineReportInfo = getBaseMapper().getExamineReportInfo(searchBO);
        if (CollectionUtil.isNotEmpty(examineReportInfo)) {
            return examineReportInfo.stream().reduce((e1, e2) -> {
                e1.setExamineStartNum(e1.getExamineStartNum() + e2.getExamineStartNum());
                e1.setExamineEndTimeAvgNum(e1.getExamineEndTimeAvgNum().add(e2.getExamineEndTimeAvgNum()));
                e1.setExamineNum(e1.getExamineNum() + e2.getExamineNum());
                e1.setExamineAvgNum(e1.getExamineAvgNum().add(e2.getExamineAvgNum()));
                return e1;
            }).get();
        }
        return CollectionUtil.getFirst(examineReportInfo);
    }

    /**
     * @return
     * @Description 仅用于xxl进行job事件轮询
     * @Author UNIQUE
     * @Date 2022/9/8
     * @Param
     **/
    @Override
    public void autoHandle(List<Long> recordIdList) {
        //1.初始化
        //2.获取提醒最新的  时间限制表数据【取小于当前时间】
        List<ExamineRecordLimit> examineRecordLimit = examineRecordLimitService.lambdaQuery().le(ExamineRecordLimit::getNoticeTime, LocalDateTime.now()).list().stream().filter(item -> (BeanUtil.isNotEmpty(item) || ObjectUtil.isNotEmpty(item.getRecordId()))).collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(examineRecordLimit)) {
            recordIdList = examineRecordLimit.stream().map(ExamineRecordLimit::getRecordId).collect(Collectors.toList());

            //examinerecord 信息
            List<ExamineRecord> examineRecordList = lambdaQuery().in(ExamineRecord::getRecordId, recordIdList).list();
            List<Long> examineIdList = examineRecordList.stream().map(ExamineRecord::getExamineId).collect(Collectors.toList());
            //examine 信息
            Map<Long, List<Examine>> examineListGroup = new HashMap<>();
            if (CollectionUtil.isNotEmpty(examineIdList)) {
                List<Examine> examineList = examineService.lambdaQuery().in(Examine::getExamineId, examineIdList).list();
                examineListGroup = examineList.stream().collect(Collectors.groupingBy(Examine::getExamineId));

            }
            //examinerecordlog 信息
            List<ExamineRecordLog> examineRecordLogList = examineRecordLogService.lambdaQuery()
                    .in(ExamineRecordLog::getRecordId, recordIdList)
                    .and(wrapper -> {
                        wrapper.or(newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus()));
                        wrapper.or(newWrapper -> newWrapper.eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.CREATE.getStatus()));
                    })
                    .list();


            Map<Long, List<ExamineRecordLog>> examineRecordLogListGroup = examineRecordLogList.stream().collect(Collectors.groupingBy(ExamineRecordLog::getRecordId));

            Map<Long, List<Examine>> finalExamineListGroup = examineListGroup;

            for (ExamineRecordLimit record : examineRecordLimit) {
                if (BeanUtil.isEmpty(record) && ObjectUtil.isEmpty(record.getRecordId())) {
                    continue;
                }
                ExamineAdvancedConfigLimitTime examineAdvancedConfigLimitTime = examineAdvancedConfigLimitTimeService.queryConfigByRecordId(record.getRecordId());
                if (ObjectUtil.isEmpty(examineAdvancedConfigLimitTime)) {
                    continue;
                }
                Integer handleType = examineAdvancedConfigLimitTime.getHandleType();
                Integer examineType = examineAdvancedConfigLimitTime.getExamineType();
                if (ObjectUtil.isEmpty(examineType)) {
                    examineType = 1;
                }
                HandleTypeEnum handleTypeEnum = HandleTypeEnum.valueOf(handleType);

                List<ExamineRecordLog> examineRecordLogs = examineRecordLogListGroup.get(record.getRecordId()).stream().filter(e -> ObjectUtil.equals(e.getExamineStatus(), ExamineStatusEnum.UNDERWAY.getStatus())).collect(Collectors.toList());

                if (CollectionUtil.isEmpty(examineRecordLogs)) {
                    continue;
                }

                List<ExamineAdvancedConfigLimitTimeUsers> examineAdvancedConfigLimitTimeUsersList = advancedConfigLimitTimeUsersService.queryHandleUserListByRecordId(record.getRecordId());

                switch (handleTypeEnum) {
                    case AUTO_NOTICE: {//自动提醒
                        //添加当前处理人
                        examineRecordLogs.forEach(r -> {
                            ExamineAdvancedConfigLimitTimeUsers limitTimeUsers = new ExamineAdvancedConfigLimitTimeUsers();
                            limitTimeUsers.setUserId(r.getExamineUserId());
                            examineAdvancedConfigLimitTimeUsersList.add(limitTimeUsers);
                        });

                        List<Long> roleList = examineAdvancedConfigLimitTimeUsersList.stream().filter(e -> ObjectUtil.equals(e.getType(), 2)).map(ExamineAdvancedConfigLimitTimeUsers::getRoleId).collect(Collectors.toList());

                        for (Long aLong : roleList) {
                            List<Long> data = adminService.queryUserIdByRoleId(aLong).getData();
                            for (Long datum : data) {
                                ExamineAdvancedConfigLimitTimeUsers limitTimeUsers = new ExamineAdvancedConfigLimitTimeUsers();
                                limitTimeUsers.setUserId(datum);
                                examineAdvancedConfigLimitTimeUsersList.add(limitTimeUsers);
                            }
                        }

                        List<Integer> parentLevelList = examineAdvancedConfigLimitTimeUsersList.stream().filter(e -> ObjectUtil.equals(e.getType(), 1)).map(ExamineAdvancedConfigLimitTimeUsers::getParentLevel).collect(Collectors.toList());

                        List<ExamineRecordLog> createLog = examineRecordLogListGroup.get(record.getRecordId()).stream().filter(e -> ObjectUtil.equals(e.getExamineStatus(), ExamineStatusEnum.CREATE.getStatus())).collect(Collectors.toList());

                        AdminUserQueryBO queryBO = new AdminUserQueryBO();
                        queryBO.setLevels(parentLevelList);
                        queryBO.setUserId(createLog.get(0).getCreateUserId());
                        List<UserInfo> data = adminService.queryParentByLevel(queryBO).getData();
                        for (UserInfo datum : data) {
                            ExamineAdvancedConfigLimitTimeUsers limitTimeUsers = new ExamineAdvancedConfigLimitTimeUsers();
                            limitTimeUsers.setUserId(datum.getUserId());
                            examineAdvancedConfigLimitTimeUsersList.add(limitTimeUsers);
                        }

                        //给待处理人发送消息通知
                        examineAdvancedConfigLimitTimeUsersList.forEach(configLimitTimeUser -> {
                            examineRecordLogs.forEach(r -> {
                                if (finalExamineListGroup.containsKey(examineAdvancedConfigLimitTime.getExamineId())) {
                                    this.addMessage(finalExamineListGroup.get(examineAdvancedConfigLimitTime.getExamineId()).get(0), r, configLimitTimeUser.getUserId(), null, null);
                                }
                            });
                        });
                        //清除限时信息
                        examineRecordLimitService.removeRecordLimit(record.getRecordId());
                        break;
                    }
                    case AUTO_FORWARD: {//自动转交
                        List<ExamineFlowFinalUser> examineFlowFinalUserList = new ArrayList<>();
                        examineAdvancedConfigLimitTimeUsersList.forEach(examineAdvancedConfigLimitTimeUser -> {
                            ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                            examineFlowFinalUser.setUserId(examineAdvancedConfigLimitTimeUser.getUserId());
                            examineFlowFinalUserList.add(examineFlowFinalUser);
                        });


                        List<Long> roleList = examineAdvancedConfigLimitTimeUsersList.stream().filter(e -> ObjectUtil.equals(e.getType(), 2)).map(ExamineAdvancedConfigLimitTimeUsers::getRoleId).collect(Collectors.toList());

                        for (Long aLong : roleList) {
                            List<Long> data = adminService.queryUserIdByRoleId(aLong).getData();
                            for (Long datum : data) {
                                ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                                examineFlowFinalUser.setUserId(datum);
                                examineFlowFinalUserList.add(examineFlowFinalUser);
                            }
                        }


                        List<Integer> parentLevelList = examineAdvancedConfigLimitTimeUsersList.stream().filter(e -> ObjectUtil.equals(e.getType(), 1)).map(ExamineAdvancedConfigLimitTimeUsers::getParentLevel).collect(Collectors.toList());

                        List<ExamineRecordLog> createLog = examineRecordLogListGroup.get(record.getRecordId()).stream().filter(e -> ObjectUtil.equals(e.getExamineStatus(), ExamineStatusEnum.CREATE.getStatus())).collect(Collectors.toList());

                        AdminUserQueryBO queryBO = new AdminUserQueryBO();
                        queryBO.setLevels(parentLevelList);
                        queryBO.setUserId(createLog.get(0).getCreateUserId());
                        List<UserInfo> data = adminService.queryParentByLevel(queryBO).getData();
                        for (UserInfo datum : data) {
                            ExamineFlowFinalUser examineFlowFinalUser = new ExamineFlowFinalUser();
                            examineFlowFinalUser.setUserId(datum.getUserId());
                            examineFlowFinalUserList.add(examineFlowFinalUser);
                        }

                        ExamineAutoForwardOthersBO examineForwardOthersBO = new ExamineAutoForwardOthersBO();
                        examineForwardOthersBO.setRecordId(record.getRecordId());
                        examineForwardOthersBO.setRecordLogId(examineRecordLogs.get(0).getLogId());
                        examineForwardOthersBO.setFlowFinalId(examineRecordLogs.get(0).getFlowId());
                        examineForwardOthersBO.setExamineFlowFinalUserList(examineFlowFinalUserList);
                        examineForwardOthersBO.setType(examineType);
                        examineForwardOthersBO.setAuditPassFlag(PassFlagEnum.FORWARD_AUTO_OUT_TIME.getType());
                        autoForwardOthers(examineForwardOthersBO);
                        //清除限时信息
                        examineRecordLimitService.removeRecordLimit(record.getRecordId());
                        break;
                    }
                    case AUTO_PASS: //自动同意
                        String auditOutEmail = null;
                        Long examineUserId = null;
                        if (CollectionUtil.isNotEmpty(examineRecordLogs)) {
                            List<ExamineRecordLog> recordLogs = examineRecordLogs.stream().sorted(Comparator.comparing(ExamineRecordLog::getCreateTime).reversed()).collect(Collectors.toList());
                            auditOutEmail = CollectionUtil.getFirst(recordLogs).getExamineUserEmail();
                            examineUserId = CollectionUtil.getFirst(recordLogs).getExamineUserId();
                        }
                        ExamineBO examineBO = new ExamineBO();
                        examineBO.setRecordId(record.getRecordId());
                        examineBO.setStatus(ExamineStatusEnum.PASS.getStatus());
                        examineBO.setPassFlag(1);
                        examineBO.setAuditPassFlag(PassFlagEnum.PASS_AUTO_OUT_TIME.getType());
                        examineBO.setRemarks("审批超时自动通过");
                        if (ObjectUtil.isNotEmpty(auditOutEmail)) {
                            examineBO.setUserEmail(auditOutEmail);
                        } else {
                            //1 依次审批 2 会签 3 或签
                            switch (examineType) {
                                case 1:
                                    examineBO.setExamineUserId(examineUserId);
                                    break;
                                case 2:
                                    examineBO.setExamineUserId(examineUserId);
                                    break;
                                case 3:
                                    examineBO.setExamineUserId(examineUserId);
                                    break;
                                default:
                                    examineBO.setExamineUserId(examineUserId);
                                    break;
                            }

                        }
                        //同方法内调用事务不生效，所以使用applicationContext获取bean
                        ApplicationContextHolder.getBean(IExamineRecordService.class).auditExamine(examineBO);
                        break;
                }
            }
        }

    }


    /**
     * @return
     * @Description 获取报下钻咧白哦
     * @Author zyh
     * @Date 2022/8/28
     * @Param
     **/
    @Override
    public BasePage<ExamineRecord> getExamineReportSubList(SuperExamineReportSubSearchBO searchBO) {
        return getBaseMapper().getExamineReportSubList(searchBO.parse(), searchBO);
    }

    /**
     * @return
     * @Description 删除过期email 对外token
     * @Author UNIQUE
     * @Date 2022/8/28
     * @Param
     **/
    @Override
    public void removeInvalidEmailToken() {
        superExamineEmailService.removeInvalidEmailToken();
    }

    @Override
    public List<ExamineRecordCustomerVO> queryExamineRecordListByTypeId(Long typeId, Long ownerUserId) {
        List<ExamineRecordCustomerVO> examineRecordCustomerVOs = new ArrayList<>();
        List<ExamineRecord> examineRecords = lambdaQuery().eq(ExamineRecord::getTypeId, typeId)
                .eq(ExamineRecord::getLabel, ExamineEnum.CRM_CUSTOMER_TEAM_MEMBER.getType())
                .list();
        if (CollUtil.isNotEmpty(examineRecords)) {
            for (ExamineRecord examineRecord : examineRecords) {
                ExamineRecordCustomerVO examineRecordVO = new ExamineRecordCustomerVO();
                Examine examine = examineService.lambdaQuery().eq(Examine::getExamineId, examineRecord.getExamineId()).one();
                if (ObjectUtil.isNotNull(examine)) {
                    examineRecordVO.setExamineName(examine.getExamineName());
                }
                String userName = UserCacheUtil.getUserName(examineRecord.getCreateUserId());
                examineRecordVO.setSubmitter(userName);
                examineRecordVO.setStatus(examineRecord.getExamineStatus());
                examineRecordVO.setStartingTime(examineRecord.getCreateTime());
                examineRecordVO.setRecordId(examineRecord.getRecordId());
                examineRecordCustomerVOs.add(examineRecordVO);
            }
        }
        return examineRecordCustomerVOs;
    }


    /**
     * 获取下次审批流程
     *
     * @param flow
     * @return
     */
    public ExamineFlow getNextFlow(ExamineFlow flow) {
        ExamineFlow examineFlow;
        if (flow.getExamineId().equals(0L)) {

            //先在同等条件id下找下个审批
            examineFlow = examineFlowService.lambdaQuery()
                    .eq(ExamineFlow::getConditionId, flow.getConditionId())
                    .eq(ExamineFlow::getBatchId, flow.getBatchId())
                    .eq(ExamineFlow::getSort, flow.getSort() + 1).one();


            if (examineFlow == null) {
                //如果同等条件id下没有下个审批，就找条件id下的第一个审批,找到上层审批
                examineFlow = examineFlowService.lambdaQuery()
                        .eq(ExamineFlow::getConditionId, flow.getConditionId())
                        .eq(ExamineFlow::getBatchId, flow.getBatchId())
                        .eq(ExamineFlow::getSort, 1).one();

                ExamineCondition condition = examineConditionService.getById(examineFlow.getConditionId());

                ExamineFlow flow1 = examineFlowService.getById(condition.getFlowId());

                //如果上层审批是条件审批，继续递归
                if (flow1.getExamineType().equals(0)) {
                    examineFlow = getNextFlow(flow1);
                } else {
                    examineFlow = examineFlowService.lambdaQuery().eq(ExamineFlow::getSort, flow1.getSort() + 1).ne(ExamineFlow::getExamineId, 0).eq(ExamineFlow::getBatchId, flow.getBatchId()).one();
                }
            }
        } else {
            examineFlow = examineFlowService.lambdaQuery().eq(ExamineFlow::getSort, flow.getSort() + 1).ne(ExamineFlow::getExamineId, 0).eq(ExamineFlow::getBatchId, flow.getBatchId()).one();
        }

        return examineFlow;
    }

    /**
     * 管理员干预
     *
     * @param examineBO
     */
    @Override
    @Transactional
    public void adminAuditExamine(ExamineAdminBO examineBO) {

        //恢复
        if (ExamineStatusEnum.RESTORE.getStatus().equals(examineBO.getStatus())) {
            //参数不能为空
            if (examineBO.getRemarks() == null || examineBO.getRecordId() == null || examineBO.getTypeId() == null) {
                throw new CrmException(ExamineCodeEnum.EXAMINE_NOT_PARAMETER_ERROR);
            }
            ExamineRecord examineRecord = getById(examineBO.getRecordId());

            //当前审批不可
            if (ObjectUtil.isEmpty(examineRecord)) {
                return;
            }
            //添加校验审批意见
            if (ObjectUtil.isEmpty(examineBO.getRemarks()) && ObjectUtil.equal(examineBO.getStatus(), ExamineStatusEnum.SKIP.getStatus())) {
                throw new CrmException(ExamineCodeEnum.EXAMINE_SKIP_OR_CANCEL_REMART_NOT_EMPTY_ERROR);
            }
            //查询当前审批日志
            ExamineRecordLog recordLog;
            LambdaQueryChainWrapper<ExamineRecordLog> chainWrapper = examineRecordLogService.lambdaQuery();
            chainWrapper.eq(ExamineRecordLog::getRecordId, examineBO.getRecordId());
            chainWrapper.orderByAsc(ExamineRecordLog::getCreateTime);
            List<ExamineRecordLog> recordLogsAll = chainWrapper.list();

            List<ExamineRecordLog> recordLogs;
            if (examineBO.getStatus().equals(ExamineStatusEnum.RESTORE.getStatus())) {
                //管理员恢复
                List<Integer> list = Arrays.asList(ExamineStatusEnum.PASS.getStatus(), ExamineStatusEnum.SKIP.getStatus(), ExamineStatusEnum.COPY.getStatus());
                recordLogs = recordLogsAll.stream().filter(e -> list.contains(e.getExamineStatus())).collect(Collectors.toList());
            } else {
                //跳过
                recordLogs = recordLogsAll.stream().filter(e -> e.getExamineStatus().equals(ExamineStatusEnum.UNDERWAY.getStatus())).collect(Collectors.toList());
            }

            recordLog = CollectionUtil.getLast(recordLogs);

            // 判断当前审核是否合法
            if (recordLog == null) {
                return;
            }
            // 查询当前审批记录
            ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());
            // 校验审核状态是否合法(已通过发起撤回进行拦截)
            moduleService.checkStatus(examineRecord.getLabel(), examineRecord.getTypeId(), examineBO.getStatus(), examineRecord.getExamineStatus());

            ExamineFlowFinal aFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, recordLog.getFlowId())
                    .eq(ExamineFlowFinal::getRecordId, recordLog.getRecordId())
                    .one();

            //管理员干预恢复 添加虚拟节点
            ExamineFlowFinal adminExamineFlowFinal = new ExamineFlowFinal();
            //管理员跳过虚拟节点
            Long generalId = BaseUtil.getNextId();
            adminExamineFlowFinal.setFlowId(generalId);
            adminExamineFlowFinal.setRecordId(examineRecord.getRecordId());
            adminExamineFlowFinal.setName("恢复操作人");
            adminExamineFlowFinal.setType(1);
            adminExamineFlowFinal.setSort(aFinal.getSort() == null ? 1 : aFinal.getSort() + 1);
            adminExamineFlowFinal.setExamineId(aFinal.getExamineId());
            adminExamineFlowFinal.setExamineType(ExamineTypeEnum.MEMBER.getType());
            adminExamineFlowFinal.setCreateTime(new Date());
            examineFlowFinalService.save(adminExamineFlowFinal);

            ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
            examineFlowFinalOptional.setUserId(UserUtil.getUserId());
            examineFlowFinalOptional.setRecordId(examineBO.getRecordId());
            examineFlowFinalOptional.setFlowId(adminExamineFlowFinal.getFlowId());
            examineFlowFinalOptional.setCreateUserId(UserUtil.getUserId());
            examineFlowFinalOptional.setCreateTime(new Date());
            examineFlowFinalOptional.setType(adminExamineFlowFinal.getType());
            examineFlowFinalOptional.setSort(1);
            //保存插入节点对应的员工
            examineFlowFinalOptionalService.save(examineFlowFinalOptional);

            ExamineRecordLog examineRecordLog = BeanUtil.copyProperties(recordLog, ExamineRecordLog.class, "logId", "passFlag", "readFlag", "relTarget", "relTargetFlowId");

            examineRecordLog.setRemarks(examineBO.getRemarks());
            examineRecordLog.setFlowId(adminExamineFlowFinal.getFlowId());
            examineRecordLog.setExamineUserId(UserUtil.getUserId());
            examineRecordLog.setExamineTime(LocalDateTime.now());
            examineRecordLog.setCreateTime(LocalDateTime.now());
            examineRecordLog.setUpdateTime(LocalDateTime.now());
            examineRecordLog.setRemarks(examineBO.getRemarks());
            examineRecordLog.setExamineStatus(ExamineStatusEnum.RESTORE.getStatus());
            examineRecordLog.setSort(1);
            examineRecordLogService.save(examineRecordLog);

            if (ObjectUtil.isNull(examineBO.getFlowId())) {
                recordLogsAll.add(examineRecordLog);
                List<ExamineRecordHistoryLog> examineRecordHistoryLogs = JSON.parseArray(JSON.toJSONString(recordLogsAll), ExamineRecordHistoryLog.class);

                for (ExamineRecordHistoryLog examineRecordHistoryLog : examineRecordHistoryLogs) {
                    examineRecordHistoryLog.setLogId(null);
                    examineRecordHistoryLog.setTypeId(examineRecord.getTypeId());
                }
                examineRecordHistoryLogService.saveBatch(examineRecordHistoryLogs);
            }

            //恢复
            updateCheckStatus(examineRecord, examineRecordLog, ExamineStatusEnum.valueOf(examineBO.getStatus()), examineBO.getFlowId(), null, null, false);

        } else if (ExamineStatusEnum.SKIP.getStatus().equals(examineBO.getStatus())) {
            //跳过
            //参数不能为空
            if (examineBO.getRemarks() == null || examineBO.getRecordId() == null || examineBO.getTypeId() == null) {
                throw new CrmException(ExamineCodeEnum.EXAMINE_NOT_PARAMETER_ERROR);
            }
            //待审核的log信息
            ExamineRecordLog underwayRecordLog = examineRecordLogService.lambdaQuery().eq(ExamineRecordLog::getExamineStatus, ExamineStatusEnum.UNDERWAY.getStatus())
                    .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId()).one();
            if (underwayRecordLog == null) {
                //代表当前审批节点为发起人自选且没有选审批人
                ExamineFlowFinal examineFlowFinal = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getRecordId, examineBO.getRecordId())
                        .orderByDesc(ExamineFlowFinal::getSort, ExamineFlowFinal::getCreateTime)
                        .last(" limit 1")
                        .one();
                ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
                examineFlowFinalOptional.setUserId(UserUtil.getUserId());
                examineFlowFinalOptional.setRecordId(examineBO.getRecordId());
                examineFlowFinalOptional.setFlowId(examineFlowFinal.getFlowId());
                examineFlowFinalOptional.setCreateUserId(UserUtil.getUserId());
                examineFlowFinalOptional.setCreateTime(new Date());
                examineFlowFinalOptional.setType(examineFlowFinal.getType());
                examineFlowFinalOptional.setSort(1);
                //保存插入节点对应的员工
                examineFlowFinalOptionalService.save(examineFlowFinalOptional);
                ExamineRecordLog examineRecordLog = new ExamineRecordLog();
                examineRecordLog.setLogId(BaseUtil.getNextId());
                examineRecordLog.setType(examineFlowFinal.getType());
                examineRecordLog.setCreateTime(LocalDateTimeUtil.now());
                examineRecordLog.setUpdateTime(null);
                examineRecordLog.setCreateUserId(UserUtil.getUserId());
                examineRecordLog.setExamineId(examineFlowFinal.getExamineId());
                examineRecordLog.setExamineRoleId(0L);
                //   在这块判断审核人状态，是否有效等
                examineRecordLog.setExamineUserId(UserUtil.getUserId());
                examineRecordLog.setExamineTime(LocalDateTimeUtil.now());
                examineRecordLog.setExamineStatus(ExamineStatusEnum.SKIP.getStatus());
                examineRecordLog.setFlowId(examineFlowFinal.getFlowId());
                examineRecordLog.setRecordId(examineFlowFinal.getRecordId());
                examineRecordLog.setSort(1);
                examineRecordLog.setBatchId(IdUtil.simpleUUID());
                examineRecordLog.setUpdateUserId(UserUtil.getUserId());
                examineRecordLogService.save(examineRecordLog);
                underwayRecordLog = examineRecordLog;

            }


            examineRecordLogService.lambdaUpdate().set(ExamineRecordLog::getExamineStatus, examineBO.getStatus())
                    .set(ExamineRecordLog::getPassFlag, PassFlagEnum.SKIP_ADMIN_HANDLE.getType())
                    .set(ExamineRecordLog::getUpdateUserId, UserUtil.getUserId())
                    .eq(ExamineRecordLog::getRecordId, examineBO.getRecordId())
                    .in(ExamineRecordLog::getExamineStatus, Arrays.asList(ExamineStatusEnum.UNDERWAY.getStatus(), ExamineStatusEnum.AWAIT.getStatus())).update();
            adminSkip(examineBO, underwayRecordLog);
        }
    }

    @Transactional
    public void adminSkip(ExamineAdminBO examineBO, ExamineRecordLog underwayRecordLog) {
        ExamineRecord examineRecord = this.lambdaQuery().eq(ExamineRecord::getRecordId, examineBO.getRecordId()).one();
        ExaminePreviewBO examinePreviewBO = new ExaminePreviewBO();
        examinePreviewBO.setLabel(examineRecord.getLabel());
        examinePreviewBO.setRecordId(examineBO.getRecordId());
        //获取预览审批流程节点
        List<ExamineFlowVO> examineFlowVOSList = examineService.getPreviewExamineFlows(examinePreviewBO);
        //当前所有要执行的节点
        List<ExamineFlowVO> examineFlowVOS = new ArrayList<>();

        for (ExamineFlowVO examineFlowVO : examineFlowVOSList) {
            if (examineFlowVO.getFlowId().equals(examineBO.getFlowId())) {
                break;
            }
            examineFlowVOS.add(examineFlowVO);
        }

        //管理员干预审批log记录
        ExamineRecordLog examineRecordLog = new ExamineRecordLog();
        //对每个节点都要跳过
        if (examineFlowVOS.size() > 0) {
            //处理跳过中间节点
            for (ExamineFlowVO examineFlowVO : examineFlowVOS) {
                //中间节点
                ExamineFlowFinal examineFlowFinal = new ExamineFlowFinal();
                examineFlowFinal.setName(examineFlowVO.getName());
                examineFlowFinal.setExamineType(examineFlowVO.getExamineType());
                examineFlowFinal.setFlowId(examineFlowVO.getFlowId());
                examineFlowFinal.setCreateTime(new Date());
                examineFlowFinal.setCreateUserId(UserUtil.getUserId());
                examineFlowFinal.setExamineId(examineRecord.getExamineId());
                examineFlowFinal.setRecordId(examineRecord.getRecordId());
                examineFlowFinal.setType(examineFlowVO.getType() == null ? 1 : examineFlowVO.getType());
                Integer maxSort = examineFlowFinalService.getMaxSort(examineRecord.getRecordId(), examineRecord.getExamineId());
                examineFlowFinal.setSort(maxSort + 1);
                examineFlowFinalService.save(examineFlowFinal);

                List<ExamineRecordLog> examineRecordLogList = new ArrayList<>();
                List<SimpleUser> userList = examineFlowVO.getUserList();
                List<ExamineFlowFinalOptional> list = castFlowOptionalUser(userList, examineFlowFinal.getFlowId(), examineFlowFinal.getRecordId(), examineFlowFinal.getType());
                for (int i = 0; i < list.size(); i++) {
                    ExamineFlowFinalOptional finalOptional = list.get(i);
                    ExamineRecordLog examineRecordLogOne = new ExamineRecordLog();
                    examineRecordLogOne.setLogId(BaseUtil.getNextId());
                    examineRecordLogOne.setType(finalOptional.getType());
                    examineRecordLogOne.setCreateTime(LocalDateTimeUtil.now());
                    examineRecordLogOne.setUpdateTime(null);
                    examineRecordLogOne.setCreateUserId(UserUtil.getUserId());
                    examineRecordLogOne.setExamineId(examineFlowFinal.getExamineId());
                    examineRecordLogOne.setExamineRoleId(0L);
                    //   在这块判断审核人状态，是否有效等
                    examineRecordLogOne.setExamineUserId(finalOptional.getUserId());
                    examineRecordLogOne.setExamineTime(LocalDateTimeUtil.now());
                    examineRecordLogOne.setExamineStatus(ExamineStatusEnum.SKIP.getStatus());
                    examineRecordLogOne.setFlowId(examineFlowFinal.getFlowId());
                    examineRecordLogOne.setRecordId(examineRecord.getRecordId());
                    examineRecordLogOne.setSort(finalOptional.getSort());
                    examineRecordLogOne.setBatchId(IdUtil.simpleUUID());
                    examineRecordLogOne.setUpdateUserId(UserUtil.getUserId());
                    examineRecordLogOne.setPassFlag(PassFlagEnum.SKIP_ADMIN_HANDLE.getType());
                    examineRecordLogOne.setExamineUserEmail(finalOptional.getEmail());
                    examineRecordLogList.add(examineRecordLogOne);
                }

                examineFlowFinalOptionalService.saveBatch(list);
                if (list.size() == 0) {
                    ExamineRecordLog examineRecordLogOne = new ExamineRecordLog();
                    examineRecordLogOne.setLogId(BaseUtil.getNextId());
                    examineRecordLogOne.setType(examineFlowFinal.getType());
                    examineRecordLogOne.setCreateTime(LocalDateTimeUtil.now());
                    examineRecordLogOne.setUpdateTime(null);
                    examineRecordLogOne.setCreateUserId(UserUtil.getUserId());
                    examineRecordLogOne.setExamineId(examineFlowFinal.getExamineId());
                    examineRecordLogOne.setExamineRoleId(0L);
                    //   在这块判断审核人状态，是否有效等
                    examineRecordLogOne.setRemarks("自动跳过");
                    examineRecordLogOne.setExamineUserId(0L);
                    examineRecordLogOne.setExamineTime(LocalDateTimeUtil.now());
                    examineRecordLogOne.setExamineStatus(ExamineStatusEnum.SKIP.getStatus());
                    examineRecordLogOne.setFlowId(examineFlowFinal.getFlowId());
                    examineRecordLogOne.setRecordId(examineRecord.getRecordId());
                    examineRecordLogOne.setSort(1);
                    examineRecordLogOne.setBatchId(IdUtil.simpleUUID());
                    examineRecordLogOne.setUpdateUserId(UserUtil.getUserId());
                    examineRecordLogOne.setPassFlag(PassFlagEnum.SKIP_AUTO_NO_USER.getType());
                    examineRecordLogList.add(examineRecordLogOne);
                }
                examineRecordLogService.saveBatch(examineRecordLogList);
                //审批存在跳过最后真是节点后加一个虚拟节点用于保存操作跳过人员记录
                if (examineFlowVOS.lastIndexOf(examineFlowVO) == examineFlowVOS.size() - 1) {
                    //表示跳过的最后一个节点  管理员干预节点
                    ExamineFlowFinal adminExamineFlowFinal = new ExamineFlowFinal();
                    //管理员跳过虚拟节点
                    Long generalId = BaseUtil.getNextId();
                    adminExamineFlowFinal.setFlowId(generalId);
                    adminExamineFlowFinal.setRecordId(examineRecord.getRecordId());
                    adminExamineFlowFinal.setInsertTarget(examineFlowVO.getFlowId());
                    adminExamineFlowFinal.setInsertFlag(2);
                    adminExamineFlowFinal.setName("跳过操作人");
                    adminExamineFlowFinal.setType(1);
                    adminExamineFlowFinal.setSort(examineFlowFinal.getSort() + 1);
                    adminExamineFlowFinal.setExamineId(examineRecord.getExamineId());
                    adminExamineFlowFinal.setExamineType(ExamineTypeEnum.MEMBER.getType());
                    adminExamineFlowFinal.setCreateTime(new Date());
                    adminExamineFlowFinal.setIsAdminSkip(true);
                    examineFlowFinalService.save(adminExamineFlowFinal);

                    ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
                    examineFlowFinalOptional.setUserId(UserUtil.getUserId());
                    examineFlowFinalOptional.setRecordId(adminExamineFlowFinal.getRecordId());
                    examineFlowFinalOptional.setFlowId(adminExamineFlowFinal.getFlowId());
                    examineFlowFinalOptional.setCreateUserId(UserUtil.getUserId());
                    examineFlowFinalOptional.setCreateTime(new Date());
                    examineFlowFinalOptional.setType(adminExamineFlowFinal.getType());
                    examineFlowFinalOptional.setSort(1);
                    //保存插入节点对应的员工
                    examineFlowFinalOptionalService.save(examineFlowFinalOptional);

                    examineRecordLog.setLogId(BaseUtil.getNextId());
                    examineRecordLog.setType(1);
                    examineRecordLog.setCreateTime(LocalDateTimeUtil.now());
                    examineRecordLog.setUpdateTime(null);
                    examineRecordLog.setCreateUserId(UserUtil.getUserId());
                    examineRecordLog.setExamineId(adminExamineFlowFinal.getExamineId());
                    examineRecordLog.setExamineRoleId(0L);
                    //   在这块判断审核人状态，是否有效等
                    examineRecordLog.setExamineUserId(UserUtil.getUserId());
                    examineRecordLog.setExamineTime(LocalDateTimeUtil.now());
                    examineRecordLog.setExamineStatus(ExamineStatusEnum.SKIP.getStatus());
                    examineRecordLog.setFlowId(generalId);
                    examineRecordLog.setRecordId(examineRecord.getRecordId());
                    examineRecordLog.setSort(1);
                    examineRecordLog.setBatchId(IdUtil.simpleUUID());
                    examineRecordLog.setUpdateUserId(UserUtil.getUserId());
                    examineRecordLog.setRemarks(examineBO.getRemarks());
                    examineRecordLogService.save(examineRecordLog);
                }
            }
        } else {
            Long flowId = underwayRecordLog.getFlowId();
            ExamineFlowFinal examineFlowVO = examineFlowFinalService.lambdaQuery().eq(ExamineFlowFinal::getFlowId, flowId)
                    .eq(ExamineFlowFinal::getRecordId, examineRecord.getRecordId()).one();

            //表示跳过的最后一个节点
            ExamineFlowFinal adminExamineFlowFinal = new ExamineFlowFinal();
            //管理员跳过虚拟节点
            Long generalId = BaseUtil.getNextId();
            adminExamineFlowFinal.setFlowId(generalId);
            adminExamineFlowFinal.setRecordId(examineRecord.getRecordId());
            adminExamineFlowFinal.setInsertTarget(examineFlowVO.getFlowId());
            adminExamineFlowFinal.setInsertFlag(2);
            adminExamineFlowFinal.setName("跳过操作人");
            adminExamineFlowFinal.setType(1);
            Integer maxSort = examineFlowFinalService.getMaxSort(examineRecord.getRecordId(), examineRecord.getExamineId());
            adminExamineFlowFinal.setSort(maxSort + 1);
            adminExamineFlowFinal.setExamineId(examineFlowVO.getExamineId());
            adminExamineFlowFinal.setExamineType(ExamineTypeEnum.MEMBER.getType());
            adminExamineFlowFinal.setCreateTime(examineFlowVO.getCreateTime());
            adminExamineFlowFinal.setIsAdminSkip(true);
            examineFlowFinalService.save(adminExamineFlowFinal);

            ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
            examineFlowFinalOptional.setUserId(UserUtil.getUserId());
            examineFlowFinalOptional.setRecordId(adminExamineFlowFinal.getRecordId());
            examineFlowFinalOptional.setFlowId(adminExamineFlowFinal.getFlowId());
            examineFlowFinalOptional.setCreateUserId(UserUtil.getUserId());
            examineFlowFinalOptional.setCreateTime(new Date());
            examineFlowFinalOptional.setType(adminExamineFlowFinal.getType());
            examineFlowFinalOptional.setSort(1);
            //保存插入节点对应的员工
            examineFlowFinalOptionalService.save(examineFlowFinalOptional);

            examineRecordLog.setLogId(BaseUtil.getNextId());
            examineRecordLog.setType(ExamineTypeEnum.MEMBER.getType());
            examineRecordLog.setCreateTime(LocalDateTimeUtil.now());
            examineRecordLog.setUpdateTime(null);
            examineRecordLog.setCreateUserId(UserUtil.getUserId());
            examineRecordLog.setExamineId(adminExamineFlowFinal.getExamineId());
            examineRecordLog.setExamineRoleId(0L);
            //   在这块判断审核人状态，是否有效等
            examineRecordLog.setExamineUserId(UserUtil.getUserId());
            examineRecordLog.setExamineTime(LocalDateTimeUtil.now());
            examineRecordLog.setExamineStatus(ExamineStatusEnum.SKIP.getStatus());
            examineRecordLog.setFlowId(generalId);
            examineRecordLog.setRecordId(examineRecord.getRecordId());
            examineRecordLog.setSort(1);
            examineRecordLog.setBatchId(IdUtil.simpleUUID());
            examineRecordLog.setUpdateUserId(UserUtil.getUserId());
            examineRecordLog.setRemarks(examineBO.getRemarks());
            examineRecordLogService.save(examineRecordLog);

        }

        if (examineBO.getFlowId() == null) {
            //说明已经是最后一层了，直接通过
            updateCheckStatus(examineRecord, examineRecordLog, ExamineStatusEnum.valueOf(ExamineStatusEnum.SKIP.getStatus()), null, null, null, false);
        } else {
            //表示最新待审批的实际审批节点
            ExamineFlow examineFlow = examineFlowService.lambdaQuery().eq(ExamineFlow::getFlowId, examineBO.getFlowId()).one();

            //跳过值最终节点
            ExamineTypeService examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

            examineFlow = examineTypeService.getAvailableFlow(examineFlow, examineRecord, null);

            examineTypeService = ApplicationContextHolder.getBean(ExamineTypeEnum.valueOf(examineFlow.getExamineType()).getServerName());

            examineTypeService.disposeFlow(examineFlow, examineRecord.getRecordId(), null, null, false);

            //处理流程委托
            examineDelegateService.disposeDelegate(examineFlow.getFlowId(), examineRecord.getRecordId(), examineRecord.getLabel());

            examineTypeService.handleRecordLogByAdvancedConfig(examineRecord.getRecordId(), examineFlow.getFlowId(), false, null);
        }

    }


    private List<ExamineFlowFinalOptional> castFlowOptionalUser(List<SimpleUser> userList, Long flowId, Long recordId, Integer type) {
        List<ExamineFlowFinalOptional> flowFinalOptionals = new ArrayList<>(userList.size());
        Long createUserId = UserUtil.getUserId();
        int i = 0;
        Date date = new Date();
        for (SimpleUser simpleUser : userList) {
            ExamineFlowFinalOptional examineFlowFinalOptional = new ExamineFlowFinalOptional();
            examineFlowFinalOptional.setCreateTime(date);
            examineFlowFinalOptional.setCreateUserId(createUserId);
            examineFlowFinalOptional.setFlowId(flowId);
            examineFlowFinalOptional.setRecordId(recordId);
            examineFlowFinalOptional.setSort(i++);
            examineFlowFinalOptional.setType(type);
            examineFlowFinalOptional.setUserId(simpleUser.getUserId());
            examineFlowFinalOptional.setEmail(simpleUser.getOuterUserEmail());
            flowFinalOptionals.add(examineFlowFinalOptional);
        }
        return flowFinalOptionals;

    }

    @Override
    public List<ExamineReturnFlowVO> adminExamineFlowId(ExaminePreviewBO examinePreviewBO) {

        List<ExamineFlowVO> previewExamineFlows = examineService.getPreviewExamineFlows(examinePreviewBO);
        List<ExamineReturnFlowVO> collect = previewExamineFlows.stream().filter(ObjectUtil::isNotNull)
                .filter(examineFlowVO -> ObjectUtil.notEqual(examineFlowVO.getExamineType(), 7))
                .map(examineFlowVO -> {
                    return ExamineReturnFlowVO.builder().name(examineFlowVO.getName()).flowId(examineFlowVO.getFlowId()).build();
                }).collect(Collectors.toList());
        ExamineRecord record = this.getById(examinePreviewBO.getRecordId());
        if (collect.size() > 0 || record.getExamineStatus().equals(ExamineStatusEnum.UNDERWAY.getStatus())) {
            collect.add(ExamineReturnFlowVO.builder().name("流程结束").build());
        }
        return collect;
    }

    @Override
    public List<?> queryAuthField(ExamineBO examineBO) {
        ExamineRecord examineRecord = getById(examineBO.getRecordId());
        if (examineRecord == null || examineBO.getFlowId() == null) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineRecord.getLabel()).getServerName());


        List<ExamineFlowAuthField> list = examineFlowAuthFieldService.lambdaQuery()
                .eq(ExamineFlowAuthField::getFlowId, examineBO.getFlowId())
                .eq(ExamineFlowAuthField::getLabel, moduleService instanceof ExamineJxcServiceImpl ? examineRecord.getLabel() : examineBO.getLabel())
                .list();

        List<ExamineFlowAuthField> collect = list.stream().filter(e -> e.getParentId() == null).collect(Collectors.toList());

        for (ExamineFlowAuthField examineFlowAuthField : collect) {
            if (examineFlowAuthField.getHasChildren() == 1) {
                List<ExamineFlowAuthField> authFields = list.stream().filter(e -> e.getParentId() != null)
                        .filter(e -> e.getParentId().equals(examineFlowAuthField.getId())).collect(Collectors.toList());
                examineFlowAuthField.setFieldExtendList(authFields);
            }
        }

        List<ExamineFlowFieldUpdateLog> fieldUpdateLogs = examineFlowFieldUpdateLogService.lambdaQuery()
                .eq(ExamineFlowFieldUpdateLog::getFlowId, examineBO.getFlowId())
                .eq(ExamineFlowFieldUpdateLog::getTypeId, examineRecord.getTypeId())
                .list();


        fieldUpdateLogs = fieldUpdateLogs.stream().filter(e -> ObjectUtil.notEqual(e.getNewValue(), e.getOldValue())).collect(Collectors.toList());

        if (moduleService instanceof ExamineJxcServiceImpl) {
            return moduleService.getAuthField(collect, examineBO.getLabel(), examineRecord.getTypeId(), fieldUpdateLogs);
        } else {
            return moduleService.getAuthField(collect, examineRecord.getLabel(), examineRecord.getTypeId(), fieldUpdateLogs);
        }

    }

    @Override
    public List<Map<String, Object>> queryExamineUpdateLog(ExamineBO examineBO) {
        List<ExamineFlowFieldUpdateLog> list = examineFlowFieldUpdateLogService.lambdaQuery()
                .eq(ExamineFlowFieldUpdateLog::getFlowId, examineBO.getFlowId())
                .eq(ExamineFlowFieldUpdateLog::getExamineId, examineBO.getExamineId())
                .eq(ExamineFlowFieldUpdateLog::getTypeId, examineBO.getTypeId())
                .list();
        if (list.size() == 0) {
            return new ArrayList<>();
        }
        list = list.stream().filter(e -> ObjectUtil.notEqual(e.getOldValue(), e.getNewValue())).collect(Collectors.toList());

        List<ExamineFlowFieldUpdateLogBO> updateLogBOS = new ArrayList<>();
        for (ExamineFlowFieldUpdateLog examineFlowFieldUpdateLog : list) {
            ExamineFlowFieldUpdateLogBO examineFlowFieldUpdateLogBO = new ExamineFlowFieldUpdateLogBO();
            BeanUtil.copyProperties(examineFlowFieldUpdateLog, examineFlowFieldUpdateLogBO);
            updateLogBOS.add(examineFlowFieldUpdateLogBO);
        }

        ExamineModuleService moduleService = ApplicationContextHolder.getBean(ExamineEnum.parseModule(examineBO.getLabel()).getServerName());

        return moduleService.queryExamineUpdateLog(updateLogBOS);

    }
}
